Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > specialize template for eg vector< T >

Reply
Thread Tools

specialize template for eg vector< T >

 
 
stinos@skynet.be
Guest
Posts: n/a
 
      01-27-2007
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!

 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      01-27-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) 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,A> const & 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
 
Reply With Quote
 
 
 
 
Alan Johnson
Guest
Posts: n/a
 
      01-27-2007
(E-Mail Removed) 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 T> void 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::string> v ;
v.push_back("string1") ;
v.push_back("string2") ;
x.Output(v) ;
}


And there you go.

--
Alan Johnson
 
Reply With Quote
 
Alan Johnson
Guest
Posts: n/a
 
      01-27-2007
Alan Johnson wrote:
> (E-Mail Removed) 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
 
Reply With Quote
 
stinos@skynet.be
Guest
Posts: n/a
 
      01-31-2007
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)


 
Reply With Quote
 
 
 
Reply

Thread Tools

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
specialize template member function of a template class toton C++ 3 01-25-2007 02:25 PM
Inability to explicitly specialize a template class within another non-specialized template class jn@ngedit.com C++ 1 02-17-2006 07:17 PM
specialize a template function that contains a template parameter sebastian C++ 1 09-17-2005 04:18 PM
How to partially specialize a class but NOT specialize a member function: mrstephengross C++ 1 08-02-2005 07:44 PM
Partially specialize a template with another template class Old Wolf C++ 4 04-08-2005 03:53 PM



Advertisments