CRTP模糊过载

时间:2013-10-10 19:31:37

标签: c++ gcc crtp

当我使用CRTP(Curiously recurring template pattern)时,当基类(显式)可转换为bool并且也可转换为Derived类型时,我收到编译器错误。如果我尝试使用Derivedostream类型输出为右值,则会发生编译器错误。例如:

    #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)是同等有效的候选人。

另外,我知道明确的bool习惯用C ++ 11已经过时了 - 再一次,需要让它在旧的编译器上工作。

有没有办法解决歧义而不会为std::ostream& operator <<重载Derived

1 个答案:

答案 0 :(得分:1)

它确实似乎是g ++ 4.1中的一个错误。它至少在4.2.3及更高版本中起作用。

此外,如果您删除隐式转换为explicit_bool_type或两个Object&转化,则编译正常。我强烈认为隐式向下转换是一个坏主意(假设您的实际实现实际上并没有通过引用返回堆栈变量)并且建议删除那些运算符,这样可以更好地修复编译错误。