c++ - "Invalid template argument"错误在 Visual Studio 但不是 GCC

标签 c++ visual-studio templates gcc

假设你有代码

template <template<class> class BaseType>
class EST16
    : public BaseType<int>
{
public:
    EST16(double d) 
    {
    }
};

template <class T>
class SCEST
{
    T y;
};
typedef EST16<SCEST> EST16_SC;
class Child
    : public EST16_SC
{
public:
    Child()
        : EST16_SC(1.0)
    {
    }

};



class NotWorkingChild
    : public EST16<SCEST>
{
public:
    NotWorkingChild()
        : EST16<SCEST>(1.0)
    {
    }

};



TEST(TemplateTest, TestInstantiate)
{
    Child child;
    NotWorkingChild notWorkingChild; 
}

Child 和 NotWorkingChild 的区别仅在于 typedef。在 GCC 中都编译,在 Visual Studio 中 NotWorkingChild 的构造函数产生以下错误:

2>..\..\..\src\itenav\test\SCKFErrorStateTest.cpp(43) : error C3200: 'SCEST<T>' : invalid template argument for template parameter 'BaseType', expected a class template
2>        with
2>        [
2>            T=int
2>        ]

您能解释一下为什么会这样吗?有没有比 typedef 更好的可移植解决方案?

谢谢!

最佳答案

错误信息是因为NotWorkingChild (间接)源自 SCEST<int> ,这使得 SCESTNotWorkingChild的范围内引用类(class) SCEST<int> , 而不是模板。 MSVC 拒绝这个是正确的,GCC4.5 也应该拒绝这个(GCC4.5 有更正确的注入(inject)类名查找)。

这是一个可能适用于两种编译器的解决方案

class NotWorkingChild
    : public EST16<SCEST>
{
public:
    NotWorkingChild()
        : EST16< ::SCEST >(1.0)
    {
    }

};

注意我们使用范围解析运算符并且需要在 :: 之前放置一个空格( token <: 否则将被视为有向字母)。


突发新闻:即使您这样做,C++0x 也能实现上述功能 EST16<SCEST> .原因是,它说如果将注入(inject)的类名传递给模板模板参数,则注入(inject)的类名将被视为模板,而不是类型。因此,对于 C++0x,GCC 将是正确执行此操作的编译器。

关于c++ - "Invalid template argument"错误在 Visual Studio 但不是 GCC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5315134/

相关文章:

c++ - 在 C++ 中链接对临时对象的调用

C++ 函数重载中的模糊调用

c++ - 将常量整数转换为值* LLVM

C++:为什么 const_cast 是邪恶的?

c++ - 我可以将纯文件链接到我的可执行文件中吗?

visual-studio - 如何在 Visual Studio 中移动 "Solution Explorer"选项卡

c# - 将 Visual Studio 资源文件放在 'Resources' 以外的文件夹中?

C++ 编译时状态变量

c++ - 如何使用 Q_LOGGING_CATEGORY 并在模板函数中引用类别而不会出现多重实现错误?

java - Xamarin Android 在 Visual Studio 中绑定(bind)并使用 Java 库