LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 02-06-2011, 07:07 AM   #1
BLXCryptor
LQ Newbie
 
Registered: Jul 2010
Posts: 7

Rep: Reputation: 0
Question Regarding C++ Template Specialization.


Good Afternoon Guys,

I am having trouble understanding some concepts regarding C++ template specialization and I was hopping you guys can help me like you did last time.

I will go right into the code and let the code do the talking.

File foo.hpp
Code:
// Template Class
template < typename T1, typename T2> struct foo {
	static const char* str;
	static const char* getStr();
};

// str template initialisation.
template < typename T1, typename T2>
const char* foo<T1, T2>::str = "str<T1   , T2   >";

// str template specialisation.
template < >
const char* foo<float, float>::str = "str<float, float>";

// getStr template implementation.
template < typename T1, typename T2>
const char* foo<T1, T2>::getStr()
{ return "getStr<T1   , T2   >"; }

// getStr template specialisation.
template < >
const char* foo<float, float>::getStr()
{ return "getStr<float, float>"; }
File main.cpp
Code:
#include <iostream>
#include "foo.hpp"
using namespace std;

int main()
{
	cout   << "For <int  , int  > foo has " << foo<int  , int  >::str
		<< " and " << foo<int  , int  >::getStr() << endl;
	cout   << "For <float, float> foo has " << foo<float, float>::str
		<< " and " << foo<float, float>::getStr() << endl;
	cout   << "For <int  , float> foo has " << foo<int  , float>::str
		<< " and " << foo<int  , float>::getStr() << endl;
	cout   << "For <float, int  > foo has " << foo<float, int  >::str
		<< " and " << foo<float, int  >::getStr() << endl;
	return 0;
}
So far so good. All works fine and the output as expected is:

For <int , int > foo has str<T1 , T2 > and getStr<T1 , T2 >
For <float, float> foo has str<float, float> and getStr<float, float>
For <int , float> foo has str<T1 , T2 > and getStr<T1 , T2 >
For <float, int > foo has str<T1 , T2 > and getStr<T1 , T2 >


Now here is where I try to get funky and mess things up.
I want to do a specialization for just one of the two parameters and add the following code into foo.hpp

Code:
template < typename T1 >
const char* foo<T1, float>::getStr()
{ return "getStr<T1   , float>"; }
Which gives the error
error: invalid use of incomplete type ‘struct foo<T1, float>’

Which of course means that I am missing the following template specialization:
Code:
template < typename T1 > struct foo < T1, float>
{
	static const char* str;
	static const char* getStr();
};
However if I add this I have duplicated the definition of foo, which as you can see in both the main and the specialization is exactly the same; and now I also have to duplicate the source implementation for the new template specialization. For this example of course it is a simple initialization of str, however in a real program it could had been a lot more source.

I know that I can get thing behaving better if I create helper classes that all depend in one parameter, however I was wondering if I am missing something, or if there are other solutions to the above problem that I have not yet find, or if they have address this in C++0x.

Can you enlighten me?

Thanks a lot guys!
 
Old 02-06-2011, 10:44 PM   #2
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
One option is to use a "traits"-type system, e.g. iterator_traits:
Code:
#include <iostream>


template <class Type1, class Type2>
struct specialized
{
	static const char name[];
};

template <class Type1, class Type2>
const char specialized <Type1, Type2> ::name[] = "<Type1, Type2>";


template <>
struct specialized <float, float>
{
	static const char name[];
};

const char specialized <float, float> ::name[] = "<float, float>";


template <class Type1>
struct specialized <Type1, float>
{
	static const char name[];
};

template <class Type1>
const char specialized <Type1, float> ::name[] = "<Type1, float>";


template <class Type1, class Type2>
struct some_class
{
	static const char *const name;

	const char *get_name() const
	{ return name; }
};

template <class Type1, class Type2>
const char *const some_class <Type1, Type2> ::name = specialized <Type1, Type2> ::name;


int main()
{
	some_class <int,   int>   int_int;
	some_class <int,   float> int_float;
	some_class <float, float> float_float;
	std::cout << "int_int: "     << int_int.get_name()     << "\n";
	std::cout << "int_float: "   << int_float.get_name()   << "\n";
	std::cout << "float_float: " << float_float.get_name() << "\n";
}
Something like that allows you to minimize explicit specialization if the only differences are typedefs and static data.

If you need to do something like that for function specialization, you can do that with static functions, although it can become a bit ugly if you need access to a lot of members in the functions:
Code:
#include <iostream>


template <class Type1, class Type2>
struct specialized
{
	static void show_values(const Type1 &vValue1, const Type2 &vValue2)
	{ std::cout << "Type1: " << vValue1 << ", Type2: " << vValue2 << "\n"; }
};


template <>
struct specialized <float, float>
{
	static void show_values(const float &vValue1, const float &vValue2)
	{ std::cout << "float: " << vValue1 << ", float: " << vValue2 << "\n"; }
};


template <class Type1>
struct specialized <Type1, float>
{
	static void show_values(const Type1 &vValue1, const float &vValue2)
	{ std::cout << "Type1: " << vValue1 << ", float: " << vValue2 << "\n"; }
};


template <class Type1, class Type2>
struct some_class
{
	some_class() : value1(), value2() {}

	void show_values() const
	{ specialized <Type1, Type2> ::show_values(value1, value2); }

	Type1 value1;
	Type2 value2;
};


int main()
{
	some_class <int,   int>   int_int;
	some_class <int,   float> int_float;
	some_class <float, float> float_float;
	int_int.show_values();
	int_float.show_values();
	float_float.show_values();
}
I think the sort of specialization you're talking about can't be done with a single class definition; therefore, you're better off finding a way to confine what's specialized to a class that only contains specialized members.
Kevin Barry
 
1 members found this post helpful.
Old 02-10-2011, 12:23 PM   #3
BLXCryptor
LQ Newbie
 
Registered: Jul 2010
Posts: 7

Original Poster
Rep: Reputation: 0
Thanks a lot! Your answer did help me!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ operator= specialization neutrino17 Programming 2 04-23-2008 06:02 AM
from django.template import Template, gives output firedancer Linux - Newbie 0 11-30-2007 02:08 PM
$#^!% template specialization headache! The_Nerd Programming 3 04-27-2007 03:45 PM
C++ Template question deiussum Programming 11 09-24-2004 08:26 AM
Explicit specialization in non namespace scope ashwinipahuja Programming 3 06-04-2004 07:16 AM


All times are GMT -5. The time now is 07:32 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration