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)
...;
}
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).
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?)
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 */
}
}
Yes. You will have to use type traits. For example:
#include <boost/type_traits/is_same.hpp>
template <typename T>
void Foo ()
{
if ((boost::is_same<T, SomeClass>::value))
...;
else if ((boost::is_same<T, SomeClass2>::value))
...;
}
Depending on what you are trying to achieve, using template specialization might be much better choice.
Also, you can use enable_if/disable_if to conditionally enable/disable certain functions/methods. Combining this with type traits will allow, for example, using one function for one set of types and another function for another set of types.
Related
Let's suppose to have a templateclass Foo:
template <typename T>
class Foo {
void foo();
};
I have another template class Bar (independent from the first one):
template <int N>
class Bar {};
Let's say, I want to specialise the foo() method for whatever Bar class.
I'd wrongly write:
template <>
template <int N>
void Foo<Bar<N> >::foo() { /* ... */ }
The compiler blames me for because the type is not complete:
error: invalid use of incomplete type 'class Foo<Bar<N> >'
void Foo<Bar<N> >::foo() { }
Code
I am using C++98, but I'd like to know if there exist different solutions in C++11.
Note
I could solve the problem specialising the entire class Foo for a generic Bar, but after I should have to define all methods.
Example Code
That's not what I want, I am looking for (if exists) more elegant solution (both C++98 and C++11) which allows me to specialise and implement only a single class method.
EDIT:
The question on SO does not explain how to specialise with a template argument. Indeed, my question shows how the compiler complains about that.
For C++11 you can SFINAE enable/disable (using std::enable_if) two differents versions of foo() inside a not specialized Foo class.
In C++98 you don't have std::enable_if but you can simulate it (give me some minutes and I try to propose an example). Sorry: my idea doesn't works because this method require the use of default template arguments for methods that is a C++11 innovation.
Another way is define a template base class for Foo(), say FooBase, insert foo() (and only foo()) in FooBase and specialize FooBase.
Another way, that works also with C++98, can be tag dispatching: you can define an unique foo(), with zero parameter, that call another foo(), with a parameter that is determined by T.
The following is a full (C++98 compilable) example
#include <iostream>
struct barWay {};
struct noBarWay {};
template <int>
struct Bar
{ };
template <typename>
struct selectType
{ typedef noBarWay type; };
template <int N>
struct selectType< Bar<N> >
{ typedef barWay type; };
template <typename T>
struct Foo
{
void foo (noBarWay const &)
{ std::cout << "not Bar version" << std::endl; }
void foo (barWay const &)
{ std::cout << "Bar version" << std::endl; }
void foo ()
{ foo(typename selectType<T>::type()); }
};
int main ()
{
Foo<int> fi;
Foo< Bar<42> > fb;
fi.foo();
fb.foo();
}
if a common base is not desirable, yet another way could be giving foo() a customization point, like a trait for example:
template <typename T>
struct foo_traits;
template <typename T>
struct Foo {
void foo(){ foo_traits<T>::foo_cp(*this); }
};
template <typename T>
struct foo_traits{ static void foo_cp(T&){/*default*/} };
template <int N>
class Bar {};
template <int N>
struct foo_traits<Bar<N>>{ static void foo_cp(Foo<Bar<N>>&){/*spec*/} };
such trait could also be an implementation detail friend, if its only purpose is to internally provide a foo() specialization for Bar's.
If you cannot specialize foo, define it so that it delegates the call to an internal foo-implementation class. Then specialize that class.
Something like this should compile in C++98 and it doesn't differ much from your original code:
template <typename T>
class Foo {
template<typename>
struct FooImpl;
public:
void foo() { FooImpl<T>()(); }
};
template <int N>
class Bar {};
template <typename T>
template <int N>
struct Foo<T>::FooImpl< Bar<N> > {
void operator()() { /* ... */ }
};
int main() {
Foo< Bar<0> > fb;
fb.foo();
Foo<int> fi;
//fi.foo();
}
The last line doesn't compile as expected (at least I got it was the expected result, just define the function call operator for FooImpl otherwise).
This way you can define selectively the specializations for which you want foo to work. In all the other cases, an attempt at using foo will result in a compilation error.
I'd like to know if there exist different solutions in C++11.
This is a classic use case for tagged dispatch, of which max66 already suggested. The approach, and even syntax, are basically the same in C++98 and C++11.
Here's a bit of a cleaner implementation than max66's, I believe (running on godbolt):
template <class T>
class Foo {
template <class>
struct tag{};
template<class U>
void foo_helper(tag<U>){std::cout << "default\n";}
void foo_helper(tag<Bar<3> >){std::cout << "specialization for Bar<3>\n";}
public:
void foo(){return foo_helper(tag<T>());}
};
The principle is the same; a client function accepting no arguments calls a helper function that constructs an empty type based on the T argument. Then normal overloading takes care of the rest.
Only here I use a templated catch-all method.
In C++11 the syntax would only change slightly; We could say tag<Bar<3>> instead of tag<Bar<3> > because new parsing rules allow the chevron for nested templates.
We could also make the tag and the templated foo_helper catch-all into variadic templates to be a little more generic:
template <class T>
class Foo {
template <class...>
struct tag{};
template<class... U>
void foo_helper(tag<U...>){std::cout << "default\n";}
void foo_helper(tag<Bar<3>>){std::cout << "specialization for Bar<3>\n";}
public:
void foo(){return foo_helper(tag<T>{});}
};
Things actually start getting pretty interesting in C++17 with the introduction of constexpr if that allows us to write what looks like normal branching logic based on T (Live Demo):
template <class T>
class Foo {
public:
void foo(){
if constexpr (std::is_same_v<T, Bar<3>>){std::cout << "Specialization for Bar<3>\n";}
else std::cout << "default\n";
}
};
As you can see, all the tag stuff goes away in favor of using a simple if statement.
We take advantage of type_traits introduced in C++11 to check the type of T against our desired type. Something like this wouldn't necessarily work previously because all branches needed to be compiled. In C++17, only the branch that is selected (at compile-time) is compiled.
Note that you could emulate this behavior as early as C++98 by using typeid (godbolt demo):
void foo(){
if (typeid(T) == typeid(Bar<3>)){std::cout << "Specialization for Bar<3>\n";}
else std::cout << "default\n";
}
However, the typeid approach is a poor choice for 2 reasons:
It's a run time check (slow) for information we know at compile-time
It's brittle because all branches must compile for all template instantiations, whereas in C++17 if constexpr only compiles the branch that is selected.
I have the following functions:
void func1(int8_t input);
void func1(int16_t input);
void func1(int32_t input);
void func1(float input);
The implementation of the four functions is the same, except for some internal value that are in accordance with the input type (int8_t, int16_t, int32_t or float).
Currently I am creating the other three functions by copy-paste but this is quite tedious.
Is there any way so that I only write 1 function (for example, func1(int8_t input);) and that at building time, the other three functions are created automatically?
Or in which this could work with no need of the other three functions? Any other solution is well appreciated.
Usage of template function is the solution for this problem:
template <typename T>
void func1(const T value)
{
// Do some stuff
}
If you need to use special internal value, which depends on input type, you can use auxiliary type traits like this:
template <typename T>
struct SomeTrait
{
static const int value = 10;
};
template <>
struct SomeTrait<float>
{
static const int value = 20;
};
template <typename T>
void func1(const T value)
{
std::cout << SomeTrait<T>::value << std::endl;
// Do some stuff
}
This is clearly needing a template function. This will require C++11
#include <type_traits>
template <typename T
// This constrains the template function instantiation to only
// integral and floating types
typename = typename std::enable_if<std::is_integral<T>::value
||
std::is_floating_point<T>::value>::type>
void func1(T input)
{
......
T tmp; // Use the same data type inside function
}
If you want to keep it simple and w/o C++11, then just do
template <typename T>
void func1(T input)
{
......
T tmp; // Use the same data type inside function
}
The disadvantage is that you cannot constrain the instantiation of this function template only to integral and floating types. You can use boost::enable_if and other type traits instead of 'std::enable_if' and std:: type_traits in this case though.
You can define it as a template function:
template<typename T> void func1(T input) {
// ...
}
Then call it like this:
float f = 1.234;
func1<float>(f);
int32_t i32 = 45678;
func1<int32_t>(i32);
You can use templates if the implementation of the functions are equal:
template <typename T>
void func1(const T value)
{
// Do some stuff
}
If the implementation is different for some input type you can specify this specialization, e.g.
void func1(const complex value)
{
// Do some stuff related to complex values
}
The best way to do this is using template function.
template <typename T>
void your_function(const T input){
// do something
}
in the other hand, you can specify your template function
template <>
void your_function(const float input){
// do some specific things
}
I have a template class, say:
template<class T>
class someClient
{
void someCallbackA() {foo_->onA();}
void someCallbackB() {foo_->onB();}
private:
T* foo_;
};
which I can instantiate with a bunch of different types T which support the onA and onB interface. I happen to have a case where two out of the several different types T I use needs a particular behavior controlled from someClient so I need to add some function doBar() to these two types (call them Edge1 and Edge2). Then I want a part of the someClient code to call foo_->doBar() but without breaking when the type of foo_ does not have that. Is there a way to use boost::enable_if to have a someClient::doBar() which will call foo_->doBar() only for those two types, but not be there, or expand to nothing if the types are not Edge1 or Edge2?
I was thinking along the lines of:
template <class T, enable_if<mpl_or<is_same<T,Edge1>, is_same<T,Edge2> > >
someClient<T>::doBar() {foo_->doBar();}
You don't need to pull any special tricks at all if you just don't call member functions that don't make sense. Template member functions are only specialized when needed (unless you add an explicit specialization). So the following code works fine:
template <typename T> struct Foo
{
void do_foo() { p->foo(); }
void do_bar() { p->bar(); }
T * p;
};
struct A { void foo() {} };
int main()
{
A a;
Foo<A> x = { &a };
x.do_foo();
}
The fact that Foo<A>::do_bar wouldn't compile is not an issue, since the member function is never instantiated. And p->bar isn't a compiler error, because p has a dependent type and the line is thus only parsed in the second lookup phase (which never happens).
I think this does what you want. I used C++11 <type_traits> instead of boost's:
struct Edge {
void doBar() { std::cout << "did Bar."; }
};
template<typename T>
class someClient
{
public:
template<typename U = T>
typename
std::enable_if<std::is_same<U, Edge>::value, void>::type
doBar() { foo_->doBar(); }
template<typename U = T>
void doBar( typename std::enable_if<!std::is_same<U, Edge>::value, void>::type* = 0 )
{ /* do nothing */ }
private:
T* foo_;
};
int main()
{
someClient<int> i;
someClient<Edge> e;
i.doBar();
e.doBar(); // outputs "did Bar."
}
doBar() needs to be template itself for this to work, explanation here: std::enable_if to conditionally compile a member function
i have following code that does not compile.
This are two functions in a template class that takes the arguments
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() {
// ...
}
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() {
// ....
}
I want to have a specialization in a member method depending on what type Ret is.
Has anybody some idea?
SFINAE does not work on non-template functions (member or non-member).
As Kerrek SB points out, making them non-member function templates will work. Or as Xeo points out, making them member function templates with a defaulted template argument will also work.
However, this is only working because the two std::enable_if conditions are non-overlapping. If you want to add a different overload for int (say), then you'll find that it doesn't scale as nicely. Depending on what you want to do, tag dispatching generally scales better than SFINAE with multiple alternatives that you want to dispatch on:
#include<type_traits>
template<typename Ret>
class Foo
{
public:
void _on_dispatched()
{
// tag dispachting: create dummy of either std::false_type or std::true_type
// almost guaranteed to be optimized away by a decent compiler
helper_on_dispatched(std::is_void<Ret>());
}
private:
void helper_on_dispatched(std::false_type)
{
// do stuff for non-void
}
void helper_on_dispatched(std::true_type)
{
// do stuff for void
}
};
int main()
{
Foo<void>()._on_dispatched();
Foo<int>()._on_dispatched();
return 0;
}
SFINAE only works on templates. Your code can be made to compile with a small modification:
template <typename Ret>
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ }
template <typename Ret>
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ }
Usage:
auto q = _on_dispatched<int>();
You can of course not deduce the return type of a function, since it is not deducible. However, you can pack this template inside another template:
template <typename T>
struct Foo
{
// insert templates here, maybe privately so
T bar() { return _on_dispatched<T>(); }
};
In my template I need to have different code parts based on whether the typename is a fundamental type or not.
Compiling this code gives a C4067 in MSVC (unexpected tokens following preprocessor directive - expected a newline):
template <typename T>
void MyClass<T>::foo()
{
// ... some code here
#if std::is_fundamental<T>::value
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
#else
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}
#endif
The template is to work with both primitive and my own (derived from ASSortable) data types and the error is thrown from template instantiation code:
template class MyClass<char>;
Trying to modify the precompiler expression to this didn't work either:
#if std::is_fundamental<T>::value == true
and produces the same exact warning.
Any ideas how to make this code warning-free?
Edit Another thing that comes to mind is to convert this into a run-time check and live with the "constant if expression" warning... Is there really no way to do this elegantly in a single function with no specializations and no extra bloat?
Edit #2 So the way I solved this (which was obvious, but somehow escaped me...) was to define a bool ASSortable::operator<(const ASSortable& _o) const {return this->before(_o);}; which does the job and makes the code clean (once again).
No more ifs or #ifdefs or any similar clutter in my code!
Can't believe I even asked that question as it had such an obvious and simple answer :(
The common pattern to solve that issue is moving the function to a base class that is specialized and abusing inheritance to bring it to your scope:
template <typename T, bool is_fundamental>
struct Foo_impl {
void foo() {
}
};
template <typename T>
struct Foo_impl<T,true>
{
void foo() { // is fundamental version
}
};
template <typename T>
class Foo : public Foo_impl<T, std::is_fundamental_type<T>::value> {
// ...
};
Another approach would be to implement those as private functions in your class and dispatch to them internally from foo based on the trait. This is really simple and a cleaner solution, but fails if one of the two versions of the foo_impl will not compile. In that case you can use, as others have suggested a template member function to resolve, but I would still offer the non-templated foo as the public interface, forwarding to a private foo_impl template. The reason is that the template in there is an implementation detail to hack conditional compilation, not part of the interface. You don't want user code calling that member function with different template arguments than the type of your own class. Borrowing from pmr's answer:
template <typename T>
struct Foo
{
template <typename U = T,
typename std::enable_if<
std::is_fundamental<U>::value, int >::type* _ = 0
>
void foo() {
std::cout << "is fundamental" << std::endl;
}
//...
That solution allows user code like:
Foo<int> f;
f.foo<std::string>();
Which will instantiate a function that you don't need nor want, and will execute the logic that you don't want. Even if users don't try to fool your class, the fact that is a template in the interface might be confusing and make users think that it is possible to call it for different types.
Preproccessor is run at an early stage of compilation, before the compiler analyzes the types and knows the meaning of std::is_fundamental<T>::value, hence it cannot work this way.
Instead, use specialization:
template<bool> void f();
template<> void f<true>() {
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
}
template<> void f<false>() {
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}
template <typename T>
void MyClass<T>::foo()
{
// ... some code here
f<std::is_fundamental<T>::value>();
}
EDIT: You're likely to need to make f a member function, however it's not directly possible since MyClass<T> is a non-specialized template. You could make f a global which delegates the call to the correct member of MyClass. However, there is another approach.
Using overloading, this becomes:
void MyClass<T>::f(const true_type&) {
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
}
void MyClass<T>::f(const false_type&) {
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}
template <typename T>
void MyClass<T>::foo()
{
// ... some code here
f(std::is_fundamental<T>::type());
}
You are mixing up states of compilation. The preprocessor is run before the actual compiler and has no knowledge of types or templates. It just performs (very) sophisticated text substitution.
There is nothing such as static if1 in current C++, so you have to resort to a different method to enable conditional compilation. For functions I would prefer enable_if.
#include <type_traits>
#include <iostream>
template <typename T>
struct Foo
{
template <typename U = T,
typename std::enable_if<
std::is_fundamental<U>::value, int >::type = 0
>
void foo() {
std::cout << "is fundamental" << std::endl;
}
template <typename U = T,
typename std::enable_if<
!(std::is_fundamental<U>::value), int >::type = 0
>
void foo() {
std::cout << "is not fundamental" << std::endl;
}
};
struct x {};
int main()
{
Foo<int> f; f.foo();
Foo<x> f2; f2.foo();
return 0;
}
1 References:
Video: Static if presented by Alexandrescu in Going Native.
n3322: Walter E. Brown's proposal for static if
n3329: Sutter, Bright and Alexandrescu's proposal for static if
It's pretty much what it says, you can't use :: in preprocessor directives. Actually, the only thing you can use after #if is a constant-expression that is defined before the compile-time. You can find some info here
std::is_fundamental<T>::value == true cannot be used at pre-processing time. I guess you would have to use some SFINAE trick with std::enable_if:
template <typename T>
typename std::enable_if<std::is_fundamental<T>::value, void>::type
MyClass<T>::foo()
{
// ... some code here
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
}
template <typename T>
typename std::enable_if<!std::is_fundamental<T>::value, void>::type
MyClass<T>::foo()
{
// ... some code here
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}