By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,134 Members | 1,276 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,134 IT Pros & Developers. It's quick & easy.

specialize template for eg vector< T >

P: n/a
Hi All!

suppose a class having a function for outputting data somehow,

class X
{
template< class tType >
void Output( const tType& arg )
{
//default ToString handles integers/doubles
myOutput( ToString( arg ) );
}

//String itself can be outputted directly
template<>
void Output< String >( const String& arg )
{
myOutput( arg );
}

void myOutput( const String& s );
};

now I'd like to add functionality in some way, be it through
specialization or overloading or just anything, so that when a
std::vector< tType is passed in, it does something like

void Output( const vector< tType >& arg )
{
const size_t nItems = arg.size();
for( size_t i = ; 0 i < nItems ; ++i )
Output( arg[ i ] );
}

Any ideas on how to achieve this? Or more general, how to find out
whether a type passed in is a plain type, or a something< type>.
I checked the boost libs a bit, because they seem to rely on template
stuff a lot, but couldn't find an answer immedeately..

Thanks in advance!

Jan 27 '07 #1
Share this Question
Share on Google+
4 Replies


P: n/a
st****@skynet.be wrote:
Hi All!

suppose a class having a function for outputting data somehow,

class X
{
template< class tType >
void Output( const tType& arg )
{
//default ToString handles integers/doubles
myOutput( ToString( arg ) );
}

//String itself can be outputted directly
template<>
void Output< String >( const String& arg )
{
myOutput( arg );
}

void myOutput( const String& s );
};

now I'd like to add functionality in some way, be it through
specialization or overloading or just anything, so that when a
std::vector< tType is passed in, it does something like

void Output( const vector< tType >& arg )
{
const size_t nItems = arg.size();
for( size_t i = ; 0 i < nItems ; ++i )
Output( arg[ i ] );
}

Any ideas on how to achieve this? Or more general, how to find out
whether a type passed in is a plain type, or a something< type>.
What about:

#include <vector>
#include <iostream>

template < typename T >
void out ( T const & t ) {
std::cout << "generic out function called.\n";
}

template < typename T, typename A >
void out ( std::vector<T,Aconst & v ) {
std::cout << "std::vector specialization called.\n";
}

int main ( void ) {
std::vector< std::vector< int ivv;
int g;
out( ivv );
out( g );
}
Best

Kai-Uwe Bux
Jan 27 '07 #2

P: n/a
st****@skynet.be wrote:
Hi All!

suppose a class having a function for outputting data somehow,

class X
{
template< class tType >
void Output( const tType& arg )
{
//default ToString handles integers/doubles
myOutput( ToString( arg ) );
}

//String itself can be outputted directly
template<>
void Output< String >( const String& arg )
{
myOutput( arg );
}

void myOutput( const String& s );
};

now I'd like to add functionality in some way, be it through
specialization or overloading or just anything, so that when a
std::vector< tType is passed in, it does something like

void Output( const vector< tType >& arg )
{
const size_t nItems = arg.size();
for( size_t i = ; 0 i < nItems ; ++i )
Output( arg[ i ] );
}

Any ideas on how to achieve this? Or more general, how to find out
whether a type passed in is a plain type, or a something< type>.
I checked the boost libs a bit, because they seem to rely on template
stuff a lot, but couldn't find an answer immedeately..

Thanks in advance!
Firstly, please try your best to post complete examples. See:
http://www.parashift.com/c++-faq-lit...t.html#faq-5.8

In example code I've provided reasonable implementations for the
functions you've left out.

Firstly, your specialization for String won't compile in at least one
compile (g++), because it requires all explicit specializations to be at
namespace scope. I'm a bit confused about whether this is standard
behavior or a g++ bug, but in any case it is only the beginning of the
headache.

What you are trying to do is called "partial template specialization".
Now the syntax that would be natural is as follows:

// WARNING: Not valid C++.
template <class U>
void Output< std::vector<U(const std::vector<U& arg)
{
// whatever
}

However, the standard only allows class templates (not functions or
member functions) to be partially specialized. What is the reason for
this restriction? As far as I can tell there is no good reason. That's
just the way it is.

So instead we'll use a helper class (a struct actually) with a static
member function to do the real work. We'll partially specialize the
class. Then we'll have our template member function forward the call to
the correct specialization of the helper class. Code can explain it
better than words:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

template <class T>
std::string ToString(T arg)
{
std::stringstream ss ;
ss << arg ;
return ss.str() ;
}

class X
{
private:

template <class T>
struct Outputter
{
static void Output(const X & x, const T & arg)
{
std::cout << "<default" ;
x.myOutput(ToString(arg)) ;
}
} ;

public:
void myOutput(const std::string & s) const
{
std::cout << "myOutput: " << s << std::endl ;
}

template <class Tvoid Output(const T & arg) const
{
Outputter<T>::Output(*this, arg) ;
}
} ;

// Defined at namespace scope because g++ won't let explicit
// specializations exist elsewhere.
template <>
struct X::Outputter<std::string>
{
static void Output(const X & x, const std::string & arg)
{
std::cout << "<string " ;
x.myOutput(arg) ;
}
} ;

// Partial template specialization.
// Defined at namespace scope because g++ won't let explicit
// specializations exist elsewhere.
template <class U>
struct X::Outputter< std::vector<U
{
static void Output(const X & x, const std::vector<U& arg)
{
std::cout << "<vector " << std::endl ;
for (std::size_t i = 0; i < arg.size(); ++i)
x.Output(arg[i]) ;
}
} ;

int main()
{
X x ;
x.Output(5) ;
x.Output(std::string("hello world")) ;

std::vector<std::stringv ;
v.push_back("string1") ;
v.push_back("string2") ;
x.Output(v) ;
}
And there you go.

--
Alan Johnson
Jan 27 '07 #3

P: n/a
Alan Johnson wrote:
st****@skynet.be wrote:
>Hi All!

suppose a class having a function for outputting data somehow,

class X
{
template< class tType >
void Output( const tType& arg )
{
//default ToString handles integers/doubles
myOutput( ToString( arg ) );
}

//String itself can be outputted directly
template<>
void Output< String >( const String& arg )
{
myOutput( arg );
}

void myOutput( const String& s );
};

now I'd like to add functionality in some way, be it through
specialization or overloading or just anything, so that when a
std::vector< tType is passed in, it does something like

void Output( const vector< tType >& arg )
{
const size_t nItems = arg.size();
for( size_t i = ; 0 i < nItems ; ++i )
Output( arg[ i ] );
}

Any ideas on how to achieve this? Or more general, how to find out
whether a type passed in is a plain type, or a something< type>.
I checked the boost libs a bit, because they seem to rely on template
stuff a lot, but couldn't find an answer immedeately..

Thanks in advance!
[snip]
Or you can dispense with all the complexity of my solution and use the
much simpler solution of function overloading as Kai-Uwe Bux suggested. :-)

--
Alan Johnson
Jan 27 '07 #4

P: n/a
mm weird, I thought I already replied saturday but I don't dee my
post.. must have clicked the wrong button or so..

@both repliers: thanks a lot, you gave the exact solution I was
looking for..
>Firstly, your specialization for String won't compile in at least one
compile (g++), because it requires all explicit specializations to be at
namespace scope. I'm a bit confused about whether this is standard
behavior or a g++ bug, but in any case it is only the beginning of the
headache.
I'm aware of that.. not sure if the standard means "specialize right
in namespace scope" (g++), or if it's more like "specialize anywhere
in namespace scope, so within a class that's in that scope is fine
too" (cl)
Jan 31 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.