2

gcc (-std=c++11 を使用した 4.7.2) でコンパイルする次のサンプル コードがあります。

template<class C>
struct template_test
{
    C testing() const
    {
        return C();
    }
};

class A;

struct test : public template_test<A> // (1)
{};

struct A
{};

int main()
{
    test t;
}

ポイント (1) で、関数template_test<A>::testing()がインスタンス化され、 の関数A、具体的にはそのデフォルト コンストラクターを使用します。したがって、testこのインスタンス化された関数を関数メンバーとして含みます。ただし、この時点Aでは不完全な型であり、C++ では不完全な型のメンバーを使用することは禁止されています。

これはpositivegcc のエラーですか、それとも別の説明がありますか?

4

3 に答える 3

4

template_test :: tests()は(1)でインスタンス化されないだけでなく、このプログラムではインスタンス化されません。テンプレートメンバーは使用時にのみインスタンス化され、testing()は使用されません。これをより明確にするために、コードを次のように少し変更します。

template<class C>
struct template_test
{
    C testing() const
    {
        return C::foo();
    }
};

class A;

struct test : public template_test<A> // (1)
{};

struct A
{};

int main()
{
    test t;
}

これもコンパイルされ、正常に実行されます。

于 2013-02-11T20:43:41.927 に答える
2

大丈夫です。メンバー関数は、testing()実際に呼び出すまでインスタンス化されません。これを確認するには、次のように書き直してみてください。

C testing() const
{
    static_assert(C::value, "Error!");
    return C();
}

関数を呼び出そうとするまでコンパイル エラーは発生しないことがわかりますが、関数に追加すると静的アサートがトリガーt.testing()されますmain()

つまり、「ポイント(1)で関数template_test<A>::testing()がインスタンス化される」という前提は正しくありません。

于 2013-02-11T20:38:26.470 に答える
1

You are instantiating a template with an incomplete type, this is OK.

The member function testing returns an instance of an incomplete type, which is not OK (but whether or not that's OK only comes into discussion when it's instantiated). However, you never call that function, so it is never instantiated, and thus there is no error. Instantiating the structure alone (and calling its constructor/destructor) is harmless.

Therefore, GCC is correct in letting you compile that. It would fail the moment you try to call testing.

于 2013-02-11T20:40:15.347 に答える