문제

I'm getting a compiler error when I use CRTP (Curiously recurring template pattern), when the base class is (explicitly) castable to bool, and also castable to the Derived type. The compiler error occurs if I try to output the Derived type as an rvalue using an ostream. For example :

    #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;
    }

This gives the compiler error:

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&)

QUESTION: Is this a compiler bug? I suspect it might be, because it only occurs on older versions of GCC, like GCC 4.1.2. Using GCC 4.8.2, it works fine. Unfortunately, I need to get it working on older compilers. If I overload std::ostream& operator << for Derived, it works. (It also works if I output an instance of Derived as an lvalue.)

I'm not sure why the compiler thinks std::ostream::operator << (bool) is an equally valid candidate.

Also, I'm aware that the explicit bool idiom is obsolete with C++11 - again, need to get this working on older compilers.

Is there a way to resolve the ambiguity without overloading std::ostream& operator << for Derived?

도움이 되었습니까?

해결책

It does indeed appear to be a bug in g++ 4.1. It works at least in 4.2.3 and later.

Additionally if you remove the implicit conversion to either explicit_bool_type or both Object& conversions it compiles fine. I would strongly argue that implicit downcasting is a bad idea (assuming your actual implementations don't actually return a stack variable by reference) and would recommend removing those operators, which then has the added benefit of fixing your compilation error.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top