基类的未定义模板参数

时间:2012-11-17 00:05:14

标签: c++ templates inheritance nested

我很确定我已经阅读了编译器无法在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;之上预先声明class derived,VS2010就会停止抱怨。在我看来,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能够throw the expected error,所以,我猜以上是VS2010中的一个错误......

3 个答案:

答案 0 :(得分:2)

此时

derived::myStruct只是一个不完整的类型。您的第二个示例也应该不起作用,遗憾的是MSVC编译器接受了大量格式错误的模板代码。一种解决方法是使用中间类来确保类型完整:

template <typename T>
class base
{
};

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

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

int main ()
{
    return 0;
}

答案 1 :(得分:1)

在C ++中,只能在定义名称后引用名称。由于derived显然尚未定义,当您引用嵌套在derived内的类来定义基类时,这不起作用。在访问它们之后声明的事物的异常是在类定义中定义的成员的函数体:这些被视为它们实际上是在类定义之后定义的。

答案 2 :(得分: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;
}

derived是模板类的更复杂的情况下,derived_myStruct也是一个模板类,具有相同的模板参数(或只是一个子集),您可以通过它们。 / p>