2017-02-21 4 views
3

VC++(2015)およびg ++ 5.4.0(--std == C++ 14)を使用して、演算子==のオーバーロード、コンパイラエラーの問題が発生しました。ここでは、コード(これは私の本当のコードベースでは、より複雑な状況の単なる抽出物である)です。テンプレートサブクラスの演算子オーバーライド問題==

#include <vector> 

template<typename T> 
struct A { 
    struct B { 
     std::vector<T> _elements; 

     // Internal cmp op. 
     bool operator==(const B &other) { 
      return _elements == other._elements; 
     } 
    }; 

    std::vector<B> _entries; 
}; 

// External cmp op. 
template<typename T> 
inline bool operator==(typename const A<T>::B &l, typename const A<T>::B & r) { 
    return l._elements == r._elements; 
} 

int main() { 
    A<int>::B b0, b1; 

    b0.operator==(b1);       // a 
    operator==<int>(b0, b1);      // b 
    b0 == b1;          // c 

    std::vector<A<int>::B> v0, v1; 

    std::equal(v0.begin(), v0.end(), v1.begin()); // d 
    v0 == v1;          // e 

    return 0; 
} 

私はVC++とg ++エラーのドイツ語版を持っているので、私はない、エラーメッセージを追加します多くの行にまたがる

VC++は(e)にエラーを示します。理由は理解できません。ベクトル< :: :: operator ==はstd :: equalを内部的に呼び出すように見え、(d)はうまくコンパイルされます。なぜこれは失敗するのですか?

g ++は外部演算子==()を受け入れないため、この短いコードを完全にコンパイルできません。両方のコンパイラで動作するA <T> :: Bの外部演算子==()を書く方法は知られていません。

私はまだclangを試していません。

多くのありがとうございます。

+0

"私はドイツ語版のVC++を持っていて、g ++のエラーは多くの行にまたがっています。英語のものはそれほど良いものではありません。 – user4581301

答えて

3

2つのエラーは、あなたのプログラムの中でありました:

// Internal cmp op. 
    bool operator==(const B &other) const { 
            ///// <- here 
     return _elements == other._elements; 
    } 

constがちょうどtypename後ろに表示することはできませんconstメンバーとキーワードのようになります。

// External cmp op. 
template<typename T> 
inline bool operator==(typename A<T>::B const& lhs, typename A<T>::B const& rhs) 
             ///// <-   here -> //// 
{ 
    return lhs._elements == rhs._elements; 
} 

Live Example

に留意されたいです。 constの配置は、通常C++ではかなり自由です。 const typename A<T>::B & lhstypename A<T>::B const& lhsの両方を書くことができますが、選択した形式はtypename const A<T>::B & lhsです。

また、メンバーoperator==または非会員のoperator==のいずれかを書きますが、両方とも決して書き込まないことに注意してください。あなたの場合、Tis not deducibletypename A<T>::Bにあるので、非会員を選択するには、醜いoperator==<int>(b0, b1)と書かなければなりません。

あなたもA<int>のオブジェクトを比較することができるように、私は非会員に

bool operator==(const A &other) const { 
    return _entries == other._entries;  
} 

を非会員のテンプレートoperator==を削除し、クラステンプレートA<T>に追加します。これによりstd::vectorの標準ライブラリoperator==が呼び出され、順番にBoperator==となります。

+0

ありがとう、これは両方の問題に役立ちます。メンバーバージョンのconstは、抽出されたコードで忘れてしまったものでした。しかし、間違ったconstが非常に多くの異なるエラーを作り出すとは思っていませんでした。 g ++のエラーメッセージはconstについて何か言及しましたが、私はそれを理解しませんでした。もう少し明確になったので、これを詳細に理解する必要があります。もう一度ありがとうございます。 –

+1

@ hob-B1Tこの回答を見つけたら、どうぞよろしくお願いします。受け入れボタンを使用してください – TemplateRex

+0

3番目のエラーは、そのオペレータテンプレートが決して使用されないということです。 –