Switch passed type from template
Solution 1
Yes, it is...but it probably won't work the way you expect.
template < typename T >
void foo()
{
if (is_same<T,SomeClass>::value) ...;
else if (is_same<T,SomeClass2>::value) ...;
}
You can get is_same
from std::
or boost::
depending on your desire/compiler. The former is only in C++0x.
The problem comes with what is in ...
. If you expect to be able to make some function call specific to those types within foo, you are sadly mistaken. A compiler error will result even though that section of code is never run when you pass in something that doesn't obey that expected interface.
To solve THAT problem you need to do something a bit different. I'd recommend tag dispatching:
struct v1_tag {};
struct v2_tag {};
template < typename T > struct someclass_version_tag;
template < > struct someclass_version_tag<SomeClass> { typedef v1_tag type; };
template < > struct someclass_version_tag<SomeClass2> { typedef v2_tag type; };
void foo(v1_tag) { ... }
void foo(v2_tag) { ... }
template < typename T > void foo()
{
typedef typename someclass_version_tag<T>::type tag;
foo(tag());
}
Note that you will not be suffering any runtime-polymorphism overhead here and with optimizations turned on it should result in the same or even smaller code size AND speed (though you shouldn't be worrying about that anyway until you've run a profiler).
Solution 2
If you want to do something specific based on the type, specialize the template:
template <typename T>
void Foo() { }
template <>
void Foo<SomeClass>() { }
template <>
void Foo<SomeClass2>() { }
// etc.
(You don't actually want to specialize the function template, though; this is for exposition only. You'll either want to overload the template if you can, or delegate to a specialized class template. For more on why and how to avoid specializing function templates, read Herb Sutter's Why Not Specialize Function Templates?)
Solution 3
No, however you can use partial specialization :
template<typename T>
struct Bar { static void foo(); };
template<typename T>
template<> inline void Bar<T>::foo() {
//generic
}
template<> inline void Bar<int>::foo() {
//stuff for int
}
template<> inline void Bar<QString>::foo() {
//QString
}
Edit Yes with type traits, however it's not really needed. Edit 2 type_traits example.
#include <type_traits>
template<typename T> void foo() {
using std::is_same;
if<is_same<T, T2>::value || is_same<T, T1>::value) {
/* stuff */
}
}
Hanut
Updated on July 17, 2022Comments
-
Hanut almost 2 years
Is it possible in C++ to check the type passed into a template function? For example:
template <typename T> void Foo() { if (typeof(SomeClass) == T) ...; else if (typeof(SomeClass2) == T) ...; }
-
Admin over 13 yearsWhat if I want to do something like
if (is_same<T, T1> || is_same<T, T2>)
? -
OneOfOne over 13 yearsThen you have to use type traits
#include <type_traits> and std::is_same<T, T2>::value
if your compiler supports C++0x (VS2010/any recent gcc) or just use boost for old compiler compatibility. -
Edward Strange over 13 yearsThat's not partial specialization, it's full specialization. There's a pretty significant difference. Probably most significant is that it would be impossible to do partial specialization that way since it's not allowed with functions of any sort.
-
Boying about 7 yearsIs it possible to return different types based on version_tag?
-
Edward Strange about 7 yearsSure. You need to come up with some way to query the information if you're stuck in C++03, or use auto in C++11 and up. So long as you don't try to return different types within the same instantiation you'll have no problem.
-
xaxxon over 6 yearsnow with C++17, you can use constexpr if statements to do this trivially