3

メソッドが純粋な仮想であり、テンプレート化された型 (外側の型から注入された) のパラメーターを取り、そのテンプレート化された型がローカル型 (関数本体で定義されている) である例を考えてみましょう。このシナリオでは、g++ でコンパイル時エラーが発生します。確かに、これは非常にまれなケースですが、実際のコードに由来しています。コンパイル可能で再現可能な例を次に示します。

#include <cstdio>

template<typename T>
struct Outer
{
    struct InnerBase
    {
        virtual void foo(T const&) = 0;
        virtual void bar(T const&) {  };
    };

    struct InnerDerived : public InnerBase
    {
        void foo(T const&) override { std::printf("virtual call foo() worked\n"); }
        void bar(T const&) override { std::printf("virtual call bar() worked\n"); }
    };

    InnerBase* inner;
    Outer() : inner(new InnerDerived()) {  }
};


struct NonLocalStruct { };

int main()
{
    struct LocalStruct { };

    Outer<NonLocalStruct> a;
    Outer<LocalStruct>    b;

    a.inner->foo(NonLocalStruct());     // fine
    a.inner->bar(NonLocalStruct());     // fine
    b.inner->foo(LocalStruct());        // causes error
    b.inner->bar(LocalStruct());        // fine

    return 0;
}

これがコンパイルエラーを引き起こす理由を誰かが説明できますか? 非ローカル型では機能するのにローカル型では機能しないのはなぜですか? 非純粋仮想メソッドが機能するのに、純粋仮想メソッドが機能しないのはなぜですか?

-std=c++11 を指定して g++ 4.8.1 を使用しています (VS2010 でもこの例を試してみましたが、コンパイルしてエラーなく実行されます)。

g++ からの正確なエラーは次のとおりです。

test.cpp:8:16: エラー: 'void Outer::InnerBase::foo(const T&) [with T = main()::LocalStruct]'、ローカル型 'const main()::LocalStruct' を使用して宣言、使用されていますが、定義されていません [-fpermissive]

4

1 に答える 1

1

私の推測では、これは g++ のバグであり、テンプレート パラメーターとしてのローカル クラスの使用に関する古い C++98 の制限に何らかの形で関連しています。

// C++98 標準

14.3.1/2 : ローカル型、リンケージのない型、名前のない型、またはこれらの型のいずれかから複合された型は、テンプレート型パラメーターのテンプレート引数として使用してはなりません。

C++11 では、この制限が解除されました。お気づきのように、Visual Studio はこれを正しくコンパイルし、Clang も同様です。回避策として、抽象関数の定義を追加すると g++ で動作します

template<typename T>
void Outer<T>::InnerBase::foo(T const&) {};

ライブの例

g++ にバグ レポートを提出する必要があると思います。

于 2013-09-25T06:36:26.607 に答える