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) 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.It compiles on VS if you change the initialiser to just refer to the template class name, EST16. I.e.: