2011-01-05 10 views
9

ヘッダーファイルに次のコードがあります。ヘッダーファイルにグローバル関数定義があり、重複するシンボルリンケージエラーを避ける

#pragma once 

class error_code { 
public: 
    unsigned __int64 hi; 
    unsigned __int64 lo;  
}; 

std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 

プロジェクトに2つのcppがある場合、このヘッダーファイルが含まれています。

エラーLNK2005: "クラスERROR_CODE __cdecl演算子|(クラスERROR_CODEのconst &、クラスViTrox :: ERROR_CODEのconst &)"(??? U @@ YA AVerror_code @ 0 @ ABV10 Z @ 0 @) は、すでに私はcppのファイルに、またはDLLファイルにoperator<<の定義を移動した場合、私は、この問題を解決することができます知っているxxx.obj

で定義されています。

しかし、私はちょうどSINGLEヘッダーファイルにそれらを持っていたいと思います。それを達成するための技術はありますか?あるいは、定義を別のファイルに分ける必要がありますか?

+0

エラーメッセージがコードスニペットと一致しません。 –

答えて

16

キーワードはinlineです。

inline std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 
+0

好奇心の外に、あなたはこの仕様がどこで動作するかを知っていますか?私はしばらくの間、これをハックとして使ってきましたが、正しく動作するという決定的な証拠は見たことがありません。 – templatetypedef

+1

IIRCでは章と節はありませんが、インラインでないとIIRCはODRに違反します(また、インラインではあるが2つ以上の異なる体でODRに違反します)。 –

+0

コンパイラは、インライン関数本体とテンプレート関数本体を参照する必要があります。それ以外の場合は、別々の翻訳単位をコンパイルするときにインライン化することも、インスタンス化することもできません。 – wilhelmtell

-1

(.hファイルではありません).cppファイルにこの関数を定義

//yoursource.cpp 
#include "yourheader.h" 

std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 
6

どちらの機能inlineます

inline std::ostream& operator<< (std::ostream& o, const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 

またはテンプレート関数ます

template<class Ch, class Tr> 
std::basic_ostream<Ch,Tr>& operator<< (std::basic_ostream<Ch,Tr>& o, 
             const error_code& e) { 
    return o << "[" << e.hi << "," << e.lo << "]"; 
} 
+0

なぜテンプレートも使えますか?テンプレートはインライン化されていますか? – Icebone1000

3

functイオンstatic。これは内部リンケージを指定するので、リンカーは、その関数が他の翻訳単位ですでに定義されているかどうかは気にしません。

または既に述べたように、inlineにすることができます。依然として外部リンケージがありますが、標準では外部インライン関数で複数の翻訳単位で定義することができます。

関連する問題