“无效的模板参数”错误在Visual Studio中但不是GCC [英] "Invalid template argument" error in Visual Studio but not GCC
问题描述
假设您有代码
模板< template< class> class BaseType>
class EST16
:public BaseType< int>
{
public:
EST16(double d)
{
}
};
模板< class T>
class SCEST
{
T y;
};
typedef EST16< SCEST> EST16_SC;
class Child
:public EST16_SC
{
public:
Child()
:EST16_SC(1.0)
{
}
};
class NotWorkingChild
:公共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):错误C3200:'SCEST< T>':模板参数'BaseType'的无效模板参数,期望类模板
2> ;与
2> [
2> T = int
2> ]
你能解释为什么会出现这种情况吗?有没有比typedef更好的便携式解决方案?
感谢!
<错误消息是因为 NotWorkingChild
从 SCEST
派生(间接),这使得<$ c $在 NotWorkingChild
范围内的c> SCEST 引用类 SCEST< int>
,而不是模板。 MSVC拒绝这个是正确的,GCC4.5也应该拒绝这个(GCC4.5有更正确的注入类名称查找)。
以下解决方案可用于两种编译器
class NotWorkingChild
:公共EST16< SCEST>
{
public:
NotWorkingChild()
:EST16< :: SCEST>(1.0)
{
}
};
请注意,我们使用范围解析运算符并需要在 ::
(令牌<:
否则会被视为有向图)。
突发新闻:即使你做了 EST16< SCEST>
。原因是,它表示如果将注入的类名称传递给模板模板参数,则将注入的类名称视为模板,而不是视为类型。因此,对于C ++ 0x,GCC是编译器正确执行的。
suppose you have the code
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 and NotWorkingChild differ only by the typedef. In GCC both compile, in Visual Studio the constructor of NotWorkingChild produces the following error:
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> ]
Can you explain why this is the case? Is there a better portable solution than the typedef?
Thanks!
The error message is because NotWorkingChild
derives (indirectly) from SCEST<int>
, which makes SCEST
inside the scope of NotWorkingChild
refer to the class SCEST<int>
, instead of the template. MSVC is correct to reject this, and GCC4.5 should reject this too (GCC4.5 has more correct injected class name lookup).
Here is a solution that might work for both compilers
class NotWorkingChild
: public EST16<SCEST>
{
public:
NotWorkingChild()
: EST16< ::SCEST >(1.0)
{
}
};
Notice that we use the scope resolution operator and need to put a space before ::
(the token <:
would otherwise be taken as a digraph).
Breaking News: C++0x will make the above work even if you do EST16<SCEST>
. The reason is, that it says that if the injected class name is passed to a template template parameter, the injected class name is treated as a template, instead of as a type. Therefor, for C++0x, GCC would be the compiler doing it correctly.
这篇关于“无效的模板参数”错误在Visual Studio中但不是GCC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!