Solved

Template Specialization of Nested Class

Posted on 2007-11-23
12
494 Views
Last Modified: 2012-06-21
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
Comment
Question by:chsalvia
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
  • +2
12 Comments
 
LVL 19

Assisted Solution

by:SteveH_UK
SteveH_UK earned 50 total points
ID: 20340436
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
 
LVL 86

Accepted Solution

by:
jkr earned 100 total points
ID: 20340454
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
 
LVL 20

Expert Comment

by:ikework
ID: 20340456
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:chsalvia
ID: 20340479
>> 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
 
LVL 19

Expert Comment

by:SteveH_UK
ID: 20340482
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
 
LVL 20

Expert Comment

by:ikework
ID: 20340494
>>  "'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
 

Author Comment

by:chsalvia
ID: 20340500
It doesn't work on GCC 4.  Maybe it's a Microsoft extension
0
 
LVL 20

Expert Comment

by:ikework
ID: 20340512
>> >> 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
 
LVL 20

Expert Comment

by:ikework
ID: 20340516
>> It doesn't work on GCC 4.  Maybe it's a Microsoft extension

can you post the error-message?
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20340694
>> 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
 
LVL 40

Expert Comment

by:evilrix
ID: 20340777
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
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 100 total points
ID: 20340804
>> 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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

724 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question