【问题标题】:Ambiguous overload with CRTPCRTP 的模棱两可的过载
【发布时间】:2013-10-10 19:31:36
【问题描述】:

当我使用 CRTP (Curiously recurring template pattern) 时出现编译器错误,当基类(显式)可转换为 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&amp; operator &lt;&lt;,它会起作用。 (如果我将Derived 的实例作为左值输出,它也可以工作。)

我不确定为什么编译器认为std::ostream::operator &lt;&lt; (bool) 是一个同样有效的候选者。

另外,我知道显式 bool 惯用语在 C++11 中已过时 - 再次,需要在较旧的编译器上使用它。

有没有办法在不为Derived 重载std::ostream&amp; operator &lt;&lt; 的情况下解决歧义?

【问题讨论】:

    标签: c++ gcc crtp


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      相关资源
      最近更新 更多