【发布时间】:2013-10-10 19:31:36
【问题描述】:
当我使用 CRTP (Curiously recurring template pattern) 时出现编译器错误,当基类(显式)可转换为 bool 并且也可转换为 Derived 类型时。如果我尝试使用ostream 将Derived 类型输出为右值,则会出现编译器错误。例如:
#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,它工作正常。不幸的是,我需要让它在旧的编译器上工作。如果我为Derived 重载std::ostream& operator <<,它会起作用。 (如果我将Derived 的实例作为左值输出,它也可以工作。)
我不确定为什么编译器认为std::ostream::operator << (bool) 是一个同样有效的候选者。
另外,我知道显式 bool 惯用语在 C++11 中已过时 - 再次,需要在较旧的编译器上使用它。
有没有办法在不为Derived 重载std::ostream& operator << 的情况下解决歧义?
【问题讨论】: