tags:

views:

181

answers:

7

In my template-ized function, I'm trying to check the type T is of a specific type. How would I do that?

p/s I knew the template specification way but I don't want to do that.

template<class T> int foo(T a) {
  // check if T of type, say, String?
}

Thanks!

+7  A: 

Instead of checking for the type use specializations. Otherwise, don't use templates.

template<class T> int foo(T a) {
      // generic implementation
}
template<> int foo(SpecialType a) {
  // will be selected by compiler 
}

SpecialType x;
OtherType y;
foo(x); // calls second, specialized version
foo(y); // calls generic version
dirkgently
+1  A: 

You can check using type_traits (available in Boost and TR1) (e.g. is_same or is_convertible) if you really want to avoid specialization.

KennyTM
Of course s/avoid/hide/
MSalters
+1  A: 

I suppose you could use the type_info returned by the typeid operator

http://www.cplusplus.com/reference/std/typeinfo/type_info/

sergiom
seems to me this is what I need. Thanks a lot! Will try it out
huy
Warning: runtime check. As such, you cannot rely on compile-time properties. E.g. you can't just use `operator[]` after checking if T==std::string.
MSalters
+1  A: 

If you don't care about compile-time, you may use boost::is_same.

bool isString = boost::is_same<T, std::string>::value;
Benoît
+2  A: 

You can perform static checks on the type that you have received (look at the boost type traits library), but unless you use specialization (or overloads, as @litb correctly points out) at one point or another, you will not be able to provide different specific implementations depending on the argument type.

Unless you have a particular reason (which you could add to the question) not to use the specialization in the interface just do specialize.

template <> int subtract( std::string const & str );
David Rodríguez - dribeas
+2  A: 

I suspect someone should tell you why it could not be a good idea to not use overloading or specialization. Consider:

template<class T> int foo(T a) {
  if(isAString<T>()) {
    return a.length();
  } else {
    return a;
  }
}

You might think on a first sight that it will work for int too, because it will only try to call length for strings. But that intuition is wrong: The compiler still checks the string branch, even if that branch is not taken at runtime. And it will find you are trying to call a member function on non-classes if T is an int.

That's why you should separate the code if you need different behavior. But better use overloading instead of specialization, since it's easier to get a clue how things work with it.

template<class T> int foo(T a) {
  return a;
}

int foo(std::string const& a) {
  return a.length();
}

You have also better separated the code for different paths of behavior. It's not all anymore clued together. Notice that with overloading, the parameters may have different type forms and the compiler will still use the correct version if both match equally well, as is the case here: One can be a reference, while the other can not.

Johannes Schaub - litb
I encountered the issue you mentioned earlier, thats why I wanted to find a way to fix, but without overloading or class specialization. I didn't think of the 'get a clue how things will work' part. Will reconsider it, thanks!
huy
@huy, you're welcome.
Johannes Schaub - litb
Modifying your example with a cast would do the trick. But it would still not be my favorite solution :)
Benoît
Johannes Schaub - litb
I agreed with @Benoît
huy
I assume what he meant is to apply typeid with typecasting and if-condition?
huy
@litb : yes, that's what i had in mind. And yes, it's ugly.
Benoît
+1  A: 

hmm because I had a large portion of same code until the 'specification' part.

You can use overloading, but if a large part of the code would work for any type, you might consider extracting the differing part into a separate function and overload that.

template <class T>
void specific(const T&);

void specific(const std::string&);

template <class T>
void something(const T& t)
{
    //code that works on all types
    specific(t);
    //more code that works on all types
}
visitor