當我使用CRTP(Curiously recurring template pattern)時,當基類明確地可轉換爲bool
,並且也可以轉換爲Derived
類型時,出現編譯器錯誤。如果我嘗試使用ostream
作爲右值輸出Derived
類型,則會發生編譯器錯誤。例如:CRTP模糊過載
#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的舊版本上,比如GCC 4.1.2。使用GCC 4.8.2,它工作正常。不幸的是,我需要讓它在較老的編譯器上工作。如果我將std::ostream& operator <<
重載爲Derived
,則可以使用。 (如果我輸出一個Derived
作爲左值的實例,它也有效。)
我不確定爲什麼編譯器認爲std::ostream::operator << (bool)
是一個同樣有效的候選人。另外,我知道顯式布爾成語已經與C++ 11過時了 - 再一次,需要讓這個工作在較老的編譯器上。
有沒有辦法解決模糊不超過std::ostream& operator <<
爲Derived
?