まず、問題を示す小さな例:
struct Bar {
enum Baz {aa, bb, cc};
Baz baz_;
operator Baz() const { return baz_; }
private:
template<typename T> operator T() const;
};
int main() {
Bar bar;
switch (bar) {
case Bar::aa:
break;
case Bar::bb:
break;
case Bar::cc:
break;
default:
break;
}
return 0;
}
このコードをg++4.7.0でコンパイルすると、次のエラーが発生します。
foo.cpp: In function ‘int main()’:
foo.cpp:12:16: error: ambiguous default type conversion from ‘Bar’
foo.cpp:12:16: error: candidate conversions include ‘template<class T> Bar::operator T() const’
私の理解では、構造体オブジェクトが「スイッチオン」されているため、コンパイラは整数型または列挙型への変換関数を見つけようとします。Bar :: Baz列挙型にパブリック変換関数を明示的に提供し、それを使用したいと思います。
私にとって紛らわしいのは、コンパイラーもプライベート変換関数を見つけて、どちらを使用するかを決定できないことです。なぜ私的な機能を考慮しているのですか?たとえば、明示的なキャストを追加するとswitch((int)bar)
、プライベート変換関数のみが一致し、コンパイラは、プライベートであるため使用できないと正しく文句を言います。では、このコンテキストではプライベート変換関数を使用できないので、なぜ2つのどちらを選択するのかが明確ではないのでしょうか。
興味深いことに、このコードはg ++ 4.6でエラーなしでコンパイルされると思います(100%確実ではありませんが)。
編集:コメントでJames McNellisが指摘しているように、プライベート変換関数がテンプレート化されているという事実もここに関連しています。