2016-06-22 16 views
1

unordered_mapのキーとして使用するために、ネームスペース内のユニオンクラスの比較演算子をオーバーロードしようとしています。ネームスペース内のクラス外の演算子オーバーロード

XH:

#include <DirectXPackedVector.h> 

namespace std 
{ 
    template<> struct hash<DirectX::PackedVector::XMUBYTEN4> 
    { 
     std::size_t operator()(DirectX::PackedVector::XMUBYTEN4 const& s) const { 
      std::size_t const h1(std::hash<uint8_t>()(s.x)); 
      std::size_t const h2(std::hash<uint8_t>()(s.y)); 
      std::size_t const h3(std::hash<uint8_t>()(s.z)); 
      std::size_t const h4(std::hash<uint8_t>()(s.w)); 
      return h1^(h2 << 1)^(h3 << 2)^(h4 << 3); 
     } 
    }; 
} 

    std::unordered_map<DirectX::PackedVector::XMUBYTEN4, unsigned int> mc_province_index; 

ハッシュが正常に動作しますが、私はそうのような比較演算子オーバーロードしようとすると:

bool operator==(const DirectX::PackedVector::XMUBYTEN4 & lhs, const DirectX::PackedVector::XMUBYTEN4 & rhs) { 
    if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w) 
     return true; 
    return false; 
} 

を私はそれをやってみました

C2678: binary '==' : no operator found which takes a left-hand operand of type 'const DirectX::PackedVector::XMUBYTEN4' (or there is no acceptable conversion) 

を取得名前空間内

namespace DirectX{ 
    namespace PackedVector{ 
     bool operator==(const DirectX::PackedVector::XMUBYTEN4 & lhs, const DirectX::PackedVector::XMUBYTEN4 & rhs) { 
      if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w) 
       return true; 
      return false; 
     } 
    } 
} 

しかし、これは私にLNK2005がオブジェクトファイルに既に定義されているというメッセージを与えてくれます。

私はここで間違っていますが、どうすればこの演算子をオーバーロードできますか?

+0

欠落インライン? –

答えて

1

operator==()inlineというように定義する必要があります。これは、おそらく1つの定義ルールに違反している可能性が高いためです。

http://en.cppreference.com/w/cpp/language/definition【一つの定義ルール]

OneとODR-使用されるすべての非インライン関数または変数 の一方のみ定義(下記参照)全体 プログラムに表示させる必要がある(を含みます任意の標準ライブラリとユーザ定義ライブラリ)。 コンパイラはこの違反を診断する必要はありませんが、違反するプログラムの動作 は未定義です。

インライン関数の場合は、 odr-usedの各変換単位で定義する必要があります。

基本的にODRに違反するバグカテゴリがあります。

  1. 複数の定義を1つのコンパイル単位で表します。そのため、ヘッダファイルにインクルードガードを使用しています。
  2. コンパイル単位レベルは違反していませんが、複数のコンパイルユニットがリンクされています。 (この場合は)

修正は簡単です:

namespace DirectX{ 
    namespace PackedVector{ 
     inline bool operator==(const DirectX::PackedVector::XMUBYTEN4 & lhs, const DirectX::PackedVector::XMUBYTEN4 & rhs) { 
      if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w) 
       return true; 
      return false; 
     } 
    } 
} 
+0

インラインを追加すると動作しますが、その理由を完全には理解できません。これは私がこの関数を定義した唯一の場所です、なぜそれが1つの定義ルールに違反していますか? –

+0

@rmファイルを別のコンパイルユニットに含めずに後でリンクしてもよろしいですか? –

+0

違反が発生しているのはそうです。ありがとうございました –

関連する問題