2012-03-07 6 views
1

スピンのためにboost::operators(clang 2.1、boost 1.48.0)を取っていて、私が説明できない以下の振る舞いに遭遇しました。私のクラスExに私自身のoperator double() constメソッドを追加すると(ユーザーが私のクラスのインスタンスでstatic_cast<double>()を慣用的に使用できるようにしたいので)、異種クラスの間でoperator==を使用しようとすると、コンパイラエラーは発生しなくなりました。 。実際、operator==はまったく呼び出されていないようです。boost :: operatorからの意図しない振る舞い

operator double() constが指定されていない場合、クラスは完全に正常に動作します(変換演算子が不足していることを除けば)。f == hを試したときに正しいコンパイラエラーが発生します。

この変換演算子を追加する正しい方法は何ですか?以下のコード。

// clang++ -std=c++0x boost-operators-example.cpp -Wall -o ex 
#include <boost/operators.hpp> 
#include <iostream> 


template <typename T, int N> 
class Ex : boost::operators<Ex<T,N>> { 
public: 
    Ex(T data) : data_(data) {}; 
    Ex& operator=(const Ex& rhs) { 
    data_ = rhs.data_; 
    return *this; 
    }; 
    T get() { 
    return data_ * N; 
    }; 
    // the troubling operator double() 
    operator double() const { 
    return double(data_)/N; 
    }; 
    bool operator<(const Ex& rhs) const { 
    return data_ < rhs.data_; 
    }; 
    bool operator==(const Ex& rhs) const { 
    return data_ == rhs.data_; 
    }; 
private: 
    T data_; 
}; 

int main(int argc, char **argv) { 
    Ex<int,4> f(1); 
    Ex<int,4> g(2); 
    Ex<int,2> h(1); 

    // this will fail for obvious reasons when operator double() is not defined 
    // 
    // error: cannot convert 'Ex<int, 4>' to 'double' without a conversion operator 

    std::cout << static_cast<double>(f) << '\n'; 


    std::cout 
    // ok 
    << (f == g) 

    // this is the error I'm supposed to get, but does not occur when I have 
    // operator double() defined 
    // 
    // error: invalid operands to binary expression 
    // ('Ex<int, 4>' and 'Ex<int, 2>') 
    // note: candidate function not viable: no known conversion from 
    // 'Ex<int, 2>' to 'const Ex<int, 4>' for 1st argument 
    // bool operator==(const Ex& rhs) const 
    << (f == h) 
    << '\n'; 
} 

答えて

5

operator double()を明示する必要があります。これにより、静的キャストは可能ですが、等価性をテストするとき(および他の場合)は暗黙の変換として使用されません。

+0

ありがとうございました。コンパイラが平等テストが暗黙の変換に匹敵すると思った方法についてもう少し詳しく説明できますか? –

+2

コンパイラがオーバーロードの解決を行うときには、組み込みの演算子が含まれます(演算子==(double、double)を含む)。そして、各引数に1つの暗黙の変換を使用することができます。その結果、有効な候補になります。それが選択されるので、より良い選択肢はありません。 –

+1

暗黙的な変換(変換演算子とコンストラクタ)は暗黙的なものです。 1つあれば、あなたのタイプは2倍に相当すると言っているでしょう。これは必要なときに便利ですが、通常はコンバージョンを明示的に保持することをお勧めします。 –