1

CRTP ( Curiously recurring template pattern ) を使用すると、基本クラスが (明示的に) にキャスト可能boolであり、Derived型にもキャスト可能である場合に、コンパイラ エラーが発生します。Derivedを使用して型を右辺値として出力しようとすると、コンパイラ エラーが発生しますostream。例えば ​​:

    #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 4.1.2 などの古いバージョンの GCC でのみ発生するため、その可能性があると思われます。GCC 4.8.2 を使用すると、正常に動作します。残念ながら、古いコンパイラで動作させる必要があります。をオーバーロードstd::ostream& operator <<するとDerived、機能します。Derived(のインスタンスを左辺値として出力する場合にも機能します。)

std::ostream::operator << (bool)コンパイラが同等に有効な候補であると考える理由がわかりません。

また、明示的な bool イディオムが C++11 では廃止されていることも認識しています。これも、古いコンパイラで機能させる必要があります。

std::ostream& operator <<をオーバーロードせずにあいまいさを解決する方法はありDerivedますか?

4

1 に答える 1

1

g++ 4.1 のバグのようです。少なくとも 4.2.3 以降では動作します。

explicit_bool_typeさらに、いずれかまたは両方の変換への暗黙的な変換を削除すると、Object&正常にコンパイルされます。暗黙的なダウンキャストは悪い考えであると強く主張します (実際の実装が参照によって実際にスタック変数を返さないと仮定すると)、これらの演算子を削除することをお勧めします。これにより、コンパイル エラーを修正するという追加の利点が得られます。

于 2013-10-10T19:58:44.870 に答える