clang-3.4 (git からコンパイル) を試してみると、私のプロジェクトの 1 つをコンパイルできず、オーバーロードされた演算子を解決する際にあいまいさを訴えていました。テンプレート化された 2 つの演算子があり、そのうちの 1 つはメンバー関数として宣言され、もう 1 つは非メンバー関数として宣言されていました。
次の SSCCE は状況を示しています。
#include <iostream>
struct ostr {
std::ostream& s;
template<class T>
ostr& operator<<(const T& x) { s << x; return *this; }
};
struct xy {
double x, y;
};
template<class Stream>
Stream& operator<<(Stream& s, const xy& x) {
s << "[" << x.x << ", " << x.y << "]";
return s;
}
int main() {
ostr os{std::cout};
xy x{4, 5};
os << "Value is: " << x <<"\n";
}
プロジェクトは以前に正常にコンパイルされましたが、この SSCCE をいくつかのコンパイラ ( gcc 4.5
、4.6
、4.7
、4.8
およびclang 3.3
) で再度チェックしましたが、すべてのコンパイラが警告なしでコンパイルしました ( を使用-Wall -Wextra -pedantic
)。すべてのコンパイラは C++11/C++0x 標準に設定されました。ctor を に追加した後、および)ostr
でも正常にコンパイルされましたMSVC 2012
2010
両方をoperator<<
非メンバーにすることは、すべてのコンパイラであいまいさを示します(予想どおり)
標準ドラフト (N3242
およびN3690
) を調べた後、メンバー関数/演算子を非メンバー関数/演算子よりも適切に一致させるものを見つけることができませんでした。
だから私は間違っていることを証明できなかったし、clang-3.4
誰が正しいのだろうか. したがって、私の質問は次のとおりです。
- このコードは有効ですか? メンバーの演算子/関数は、非メンバーのものよりも適切に一致する必要がありますが、これは clang-3.4 のバグですか?
- それとも、他のすべてのコンパイラが間違っている/寛容すぎるのでしょうか?
operator<<
2 番目の関数をテンプレート化されていない関数 (std::ostream
テンプレート パラメーターの代わりに使用) に変更すると、あいまいさが解決され、期待どおりに機能することは承知していますが、それはここでのポイントではありません。