"Invalid template argument" error in Visual Studio but not 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()
开发者_JAVA技巧 : 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.
It compiles on VS if you change the initialiser to just refer to the template class name, EST16. I.e.:
class NotWorkingChild : public EST16<SCEST>
{
public:
NotWorkingChild()
: EST16(1.0)
{
}
};
精彩评论