“无效的模板参数” Visual Studio 中出现错误,但 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 更好的便携式解决方案?
谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该错误消息是因为
NotWorkingChild
派生(间接)自SCEST
,这使得SCEST
在NotWorkingChild
的范围内code> 引用类SCEST
,而不是模板。 MSVC 正确地拒绝了这一点,GCC4.5 也应该拒绝这一点(GCC4.5 有更正确的注入类名查找)。这是一个可能适用于两种编译器的解决方案
请注意,我们使用范围解析运算符,并且需要在
::
之前放置一个空格(否则标记<:
将是视为有向图)。突发新闻:即使您执行
EST16
,C++0x 也会使上述工作正常进行。原因是,它表示如果将注入的类名传递给模板模板参数,则注入的类名将被视为模板,而不是类型。因此,对于 C++0x,GCC 将是正确执行此操作的编译器。The error message is because
NotWorkingChild
derives (indirectly) fromSCEST<int>
, which makesSCEST
inside the scope ofNotWorkingChild
refer to the classSCEST<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
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.如果您将初始化程序更改为仅引用模板类名称 EST16,它会在 VS 上编译。 IE:
It compiles on VS if you change the initialiser to just refer to the template class name, EST16. I.e.: