Template Specialization of Nested Class

I understand that template specializations are only valid in the namespace scope.  So, in order to specialize a nested class, you need to define the specialization outside the class declaration.

Here, I try to specialize a nested class inside a templated class:

template <class T>
class A
{
     template <bool B>
     struct Test;
};

template <class T>
template<>
struct A<T>::Test<true> { };

However, the above code doesn't compile.  Is there something wrong with my syntax?
chsalviaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SteveH_UKCommented:
Yes, you cannot define a structure in this way.

The structure must be fully defined in the class definition, but referring to B (and it should be template <class B> struct Test) in its definition.

as follows:

Also, as you can see, you cannot define a per-value (using true) definition like this.
template <class T>
class A
{
     template <class B>
     struct Test {
 
     };
};

Open in new window

0
jkrCommented:
MS documents that at http://msdn2.microsoft.com/en-us/library/b11ck5wk(VS.80).aspx

"'specialization' : an explicit specialization of a template member must be a member of an explicit specialization"

// C3212.cpp
// compile with: /LD
template <class T>
struct S {
   template <class T1>
   struct S1;
};


template <class T>   // C3212
template <>
struct S<T>::S1<int> {};

/*
// try the following instead
template <>
template <>
struct S<int>::S1<int> {};
*/

/*
// or, the following
template <>
struct S<int> {
   template <class T1>
   struct S1;
};

template <>
struct S<int>::S1<int> {
};
*/
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ikeworkCommented:
either you do the specialization inside of the class:

template <class T>
class A
{
public:
     template <class B>
     struct Test
     {
         B val;
     };

     template <>
     struct Test<bool>
     {
         bool val;
     };
};


or you need to specialize both template-parameters:


template <class T>
class A
{
public:
     template <class B>
     struct Test
     {
         B val;
     };

};

template<>
template<>
struct A<int>::Test<bool>
{
     bool val;
};


ike
0
OWASP: Forgery and Phishing

Learn the techniques to avoid forgery and phishing attacks and the types of attacks an application or network may face.

chsalviaAuthor Commented:
>> either you do the specialization inside of the class:

I don't think you can do this.  Template specialization only seems to work in the namespace scope.
0
SteveH_UKCommented:
In my view, none of this would be good code:

1)  it is not readable
2)  it really doesn't serve any purpose, certainly not one that could be done differently
3)  it may use some Microsoft specific extensions
0
ikeworkCommented:
>>  "'specialization' : an explicit specialization of a template member must be a member of an explicit specialization"

mh .. the following works with VC8:

template <class T>
class A
{
public:
     template <class B>
     struct Test
     {
         Test() { printf( "no specialization\n" ); }
         B val;
     };

     template <>
     struct Test<bool>
     {
         Test() { printf( "specialization called\n" ); }
         bool val;
     };
};


int main
{
    class A<int>::Test<bool> C;
    class A<int>::Test<int> D;

    return 0;
}

output is:

  specialization called
  no specialization

so it seems to work ..


ike
0
chsalviaAuthor Commented:
It doesn't work on GCC 4.  Maybe it's a Microsoft extension
0
ikeworkCommented:
>> >> either you do the specialization inside of the class:

>>I don't think you can do this.  Template specialization only seems to work in the namespace scope.

run the code from my last post .. ;)
0
ikeworkCommented:
>> It doesn't work on GCC 4.  Maybe it's a Microsoft extension

can you post the error-message?
0
evilrixSenior Software Engineer (Avast)Commented:
>> the following works with VC8
It's wrong, gcc4 is right! The standard states the specialization should only take place at namespace level -- VC8 (like in many other areas) ignores this!

>> can you post the error-message?
error: explicit specialization in non-namespace scope 'class A<T>'

The compiler will not allow the template specialization of Test because the enclosing class of class A is not explicitly specialized. Basically, as jkr has already stated, you need to specialize the outer before you can specialize the inner.

error C3212: 'A<T>::Test<true>' : an explicit specialization of a template member must be a member of an explicit specialization
0
evilrixSenior Software Engineer (Avast)Commented:
You can most likely achieve what you want by partial specialization of A, thus: -
#include <iostream>
 
template <class T, bool B>
struct A
{
	struct Test;
};
 
template <class T>
struct A<T, true>
{
	struct Test
	{
		static bool foo() { return true; }
	};
};
 
template <class T>
struct A<T, false>
{
	struct Test
	{
		static bool foo() { return false; }
	};
};
 
int main ()
{
	std::cout << "true = " << A<int, true>::Test::foo() << std::endl;
	std::cout << "false = "  << A<int, false>::Test::foo() << std::endl;
}

Open in new window

0
evilrixSenior Software Engineer (Avast)Commented:
>> Yes, you cannot define a structure in this way.
Refering to: -

template <bool B>
     struct Test;

That is perfectly valid code. It is declaring the existence of a template to the template compiler. If the definition of the template is never found then only the specializations of it can be instantiated.

E.g.
#include <iostream>
 
enum ACTIONS { JUMP, DUCK, UNKNOWN };
 
template <ACTIONS>
struct Action;
 
template <>
struct Action<JUMP>
{
	static void do_it()
	{
		std::cout << "Jump" << std::endl;
	}
};
 
template <>
struct Action<DUCK>
{
	static void do_it()
	{
		std::cout << "Duck" << std::endl;
	}
};
 
 
 
int main ()
{
	Action<JUMP>::do_it();
	Action<DUCK>::do_it();
 
	// This one won't compile as we've never defined the specialization
	//Action<UNKNOWN>::do_it();
}

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.