CRTP 的不明确过载

Ambiguous overload with CRTP

本文关键字:不明确 CRTP      更新时间:2023-10-16

当我使用 CRTP(奇怪的重复模板模式(时,当我使用基类(显式(可强制转换为bool 时,我收到编译器错误,并且也可以转换为Derived类型。 如果我尝试使用 ostreamDerived类型输出为右值,则会发生编译器错误。 例如:

    #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)是一个同样有效的候选者。

另外,我知道明确的布尔习语在 C++11 中已经过时了 - 同样,需要在较旧的编译器上使用它。

有没有办法在不使Derived std::ostream& operator <<过载的情况下解决歧义?

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

此外,如果删除隐式转换为explicit_bool_type或两者Object&转换,则编译良好。我强烈认为隐式下铸是一个坏主意(假设您的实际实现实际上并没有通过引用返回堆栈变量(,并建议删除这些运算符,这样还有修复编译错误的额外好处。