CRTP ( Curiously recurring template pattern ) を使用すると、基本クラスが (明示的に) にキャスト可能bool
であり、Derived
型にもキャスト可能である場合に、コンパイラ エラーが発生します。Derived
を使用して型を右辺値として出力しようとすると、コンパイラ エラーが発生しますostream
。例えば :
#include <iostream>
using namespace std;
template <class Object>
class Base
{
private:
typedef void (Base::*explicit_bool_type)() const;
void explicit_bool_idiom() const { }
public:
operator explicit_bool_type() const
{
return &Base::explicit_bool_idiom;
}
operator Object& ()
{
return Object();
}
operator const Object& () const
{
return Object();
}
};
class Derived : public Base<Derived>
{
public:
friend std::ostream& operator << (std::ostream& os, const Derived& d)
{
os << "abc";
return os;
}
};
int main()
{
std::cout << Derived() << std::endl;
}
これにより、コンパイラ エラーが発生します。
test2.cpp:42: error: ambiguous overload for ‘operator<<’ in ‘std::cout << Derived()’
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:102: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
test2.cpp:32: note: std::ostream& operator<<(std::ostream&, const Derived&)
質問: これはコンパイラのバグですか? GCC 4.1.2 などの古いバージョンの GCC でのみ発生するため、その可能性があると思われます。GCC 4.8.2 を使用すると、正常に動作します。残念ながら、古いコンパイラで動作させる必要があります。をオーバーロードstd::ostream& operator <<
するとDerived
、機能します。Derived
(のインスタンスを左辺値として出力する場合にも機能します。)
std::ostream::operator << (bool)
コンパイラが同等に有効な候補であると考える理由がわかりません。
また、明示的な bool イディオムが C++11 では廃止されていることも認識しています。これも、古いコンパイラで機能させる必要があります。
std::ostream& operator <<
をオーバーロードせずにあいまいさを解決する方法はありDerived
ますか?