4

コンパイラがSOのどこかでこのコードを処理できない理由を読んだことは間違いありませんが、数時間検索してもまだ見つかりません。関連するコードは次のとおりです。

#include <iostream>

template <typename T>
class base
{
};

class derived : base<derived::myStruct>
{
public:
    struct myStruct
    {
    };
};

int main ()
{
    return 0;
}

問題は、パーサーがbase<derived::myStruct>解析する前に最初に特殊化を生成しようとするderivedため、「エラーC2065:'myStruct':宣言されていない識別子」というエラーが発生することです。struct myStruct;ばかげたトリックとして、すぐ上で事前に宣言すると、VS2010が文句を言うのをやめることに気づきましたclass derived。私の意見では、myStruct内部にバインドする必要がありderived、このコードは同じエラーをスローするはずです:

#include <iostream>

template <typename T>
class base
{
};

struct myStruct;

class derived : base<derived::myStruct>
{
public:
    struct myStruct
    {
    };
};

int main ()
{
    return 0;
}

更新:gcc-4.5.1は予期されたエラーをスローできるので、上記はVS2010のバグだと思います...

4

3 に答える 3

2

derived::myStructこの時点では、単に不完全なタイプです。2番目の例も機能しないはずです。残念ながら、MSVCコンパイラは多くの不正な形式のテンプレートコードを受け入れます。回避策の1つは、中間クラスを使用して、型が完全であることを確認することです。

template <typename T>
class base
{
};

class middle
{
public:
    struct myStruct
    {
    };
};

class derived : public middle, base<middle::myStruct>
{
};

int main ()
{
    return 0;
}
于 2012-11-17T00:26:00.313 に答える
1

C ++では、名前が定義された後にのみ名前を参照できます。derivedは明らかにまだ定義されていないため、内部にネストされたクラスを参照して基本derivedクラスを定義する場合、これは機能しません。アクセス後に宣言されるものの例外は、クラス定義内で定義されたメンバーの関数本体の場合です。これらは、クラス定義の後に実際に定義されているかのように扱われます。

于 2012-11-17T00:11:43.150 に答える
1

myStruct回避策は、の外で宣言することですderived

#include <iostream>

template <typename T>
class base
{
};

struct derived_myStruct
{
};

class derived : base<derived_myStruct>
{
public:
    typedef derived_myStruct myStruct;
};

int main ()
{
    return 0;
}

がテンプレートクラスであるより複雑なケースでderivedderived_myStruct、同じテンプレートパラメータ(または単にサブセット)を持つテンプレートクラスでもあり、それらを通過させます。

于 2012-11-17T00:24:51.590 に答える