Reputation: 2765
I am referring to this example SFINAE example,
I have tried to run the sample,
//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
using type = T;
};
template <typename T>
void do_stuff(typename enable_if<std::is_integral<T>::value, T>::type &t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
void do_stuff(typename enable_if<std::is_class<T>::value, T>::type &t) {
std::cout<<"Class selected " <<std::endl;
}
int main()
{
int t =25;
do_stuff(t);
return 0;
}
But this wont compile, may I know why?
Upvotes: 1
Views: 323
Reputation: 66200
But this wont compile, may I know why?
Because, calling do_stuff()
the type T
can't be deduced through enable_if
.
But works if you call do_stuff()
explicating the type T
int t =25;
do_stuff<int>(t); // compile
To avoid this problem, I suggest you the solution proposed by Nicolas Tisserand (+1) (there is no need to explicate void
as second parameter of enable_if
because is the default)
template <typename T>
typename enable_if<std::is_integral<T>::value>::type
do_stuff(T& t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
typename enable_if<std::is_class<T>::value>::type
do_stuff(T& t) {
std::cout<<"Class selected " <<std::endl;
}
with SFINAE enabled through return type.
This way the type T
is deducible from the argument, so you doesn't need to explicate it.
Upvotes: 0
Reputation: 17197
In addition to the other solutions, if you don't want the enable_if
as a return value, you can pass it as a parameter type which is then part of the function signature:
#include <type_traits>
#include <iostream>
//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
using type = int; // must be a non-type template parameter
};
template <typename T, typename enable_if<std::is_integral<T>::value, T>::type = 0>
void do_stuff(T &t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T, typename enable_if<std::is_class<T>::value, T>::type = 0>
void do_stuff(T &t) {
std::cout<<"Class selected " <<std::endl;
}
class Foo
{
public:
Foo() = default;
};
int main()
{
int t =25;
Foo f;
do_stuff(t);
do_stuff(f);
return 0;
}
Upvotes: 3
Reputation: 488
This works for me:
template <typename T>
typename enable_if<std::is_integral<T>::value, void>::type
do_stuff(T& t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
typename enable_if<std::is_class<T>::value, void>::type
do_stuff(T& t) {
std::cout<<"Class selected " <<std::endl;
}
The problem was that the enable_if
static calls were applied to the function parameters instead of the return types.
Upvotes: 1