2011-03-15 54 views
8

假设你的代码“无效的模板参数”错误,但不是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; 
} 

儿童和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更好的便携式解决方案?

谢谢!

+1

你有没有写过任何实际实例化和使用模板类的代码?我的意思是说,“主”。可能发生的一件事情是,VCC在看到'typedef'时测试实例化,而GCC在实际使用其中一个子类之前不会感到烦恼。如果那是真的,那么只要你真正编写使用其中一个子类模板的代码,你也会在GCC中得到错误。 – phooji 2011-03-15 17:09:13

+0

是的,我做到了。 TEST宏创建一个实际从main()调用的Google测试。 – Philipp 2011-03-15 17:25:50

+0

对不起 - 'TEST'宏是在我滚动截断之后,所以我错过了它。我不是100%为什么会失败,但是我已经发布了一个替代方法,它应该在编译器中更具可移植性。这也是更可读,在我的愚蠢观点:) – phooji 2011-03-15 17:39:16

回答

11

该错误消息是因为从SCEST<int>NotWorkingChild导出(间接地),这使得内部SCESTNotWorkingChild范围指代替模板到类SCEST<int>,。 MSVC拒绝这个是正确的,GCC4.5也应该拒绝这个(GCC4.5有更正确的注入类名称查找)。

这里是一个可能的两种编译器

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

}; 

注意,我们使用范围解析操作,需要把一个空间::(令牌<:否则会被视为一个有向图)前工作的解决方案。


最新新闻:C++ 0x中将会使即使你EST16<SCEST>上述工作。原因是,它表示如果将注入的类名称传递给模板模板参数,则将注入的类名称视为模板,而不是视为类型。因此,对于C++ 0x,GCC是编译器正确执行的。

+0

似乎VS“14”CTP仍然需要范围解析运算符。 – 2014-11-29 18:37:02

2

它在VS上进行编译,如果您更改初始值以仅引用模板类名称EST16。即:

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

这是正确的,但我正在寻找一个便携式的解决方案,这不会与GCC编译:-( – Philipp 2011-03-15 18:42:21