• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 521
  • Last Modified:

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?
0
chsalvia
Asked:
chsalvia
  • 4
  • 3
  • 2
  • +2
3 Solutions
 
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
 
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 3
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now