Consider next example :
#include <iostream>
#include <typeinfo>
template< int N, typename T >
struct B
{
struct C;
};
template< typename T >
struct B< 0, T >::C
{
typedef T type;
};
template< int N, typename T >
struct B< N, T >::C
{
typedef T type[N];
};
int main()
{
std::cout<<"n=0 type = " << typeid( B< 0, float >::C::type ).name() << std::endl;
std::cout<<"n=5 type = " << typeid( B< 5, float >::C::type ).name() << std::endl;
}
When compiled using g++ (version 4.3.0)
g++ dfg.cpp -ansi -pedantic -Wall
the compile error is :
dfg.cpp:13: error: qualified name does not name a class before ‘{’ token
dfg.cpp: In instantiation of ‘B<0, float>::C’:
dfg.cpp:25: instantiated from here
dfg.cpp:20: error: ISO C++ forbids zero-size array
What I am really trying to archive is to have different Imp implementation depending on the enum value (in the example, instead of an enum, I used int, but it shouldn't matter).
Can someone explain why is this not allowed? Why am I getting the first error? (this one : qualified name does not name a class before ‘{’ token)
Regarding the pimpl implementation depending on a template parameter, I created a new question (with better example) here
This is not valid:
You can specialize members of class templates, but only for implicit instantiations of those class templates. This means in plain English: Only if you give values for all the template arguments of the enclosing class template (whose member you need to specialize).
What you wrote is the definition of a
B<0, T>::C
, which is a member of a class template partial specialization ofB<N, T>
. Such a partial specialization does not exist, therefor, the compiler errored out.You have several options to solve this. One is
Note that explicit specializations (non-partial) cannot be put into the class template directly (so,
template<> struct CMember<0, int> { ... }
would be ill-formed when writting inside the body ofB
). You would need to define the "selector" template outsideB
then (perhaps in adetail
namespace).Other alternatives include deriving from
CMember
and inheriting its typedefs.You can't define
C
outsideB
this way -C
doesn't exist for theB
specialization you're creating. If you want to specialize B::C, you need to specialize B. Are you trying to do the following?Alternatively, you can do something like:
This partially specializes B for 0 and forward declares C, so that
B<0, T>::C
can be defined.