In code:
template<class T>
struct is_builtin
{
enum {value = 0};
};
template<>
struct is_builtin<char>
{
enum {value = 1};
};
template<>
struct is_builtin<int>
{
enum {value = 1};
};
template<>
struct is_builtin<double>
{
enum {value = 1};
};
template<class T>
struct My
{
typename enable_if<is_builtin<T>::value,void>::type f(T arg)
{
std::cout << "Built-in as a param.\n";
}
typename enable_if<!is_builtin<T>::value,void>::type f(T arg)
{
std::cout << "Non - built-in as a param.\n";
}
};
struct A
{
};
int main()
{
A a;
My<int> m;
My<A> ma;
m.f(1);
ma.f(a);
return 0;
}
I'm getting an error:
error C2039: 'type' : is not a member of 'std::tr1::enable_if<_Test,_Type>'
Obviously I don't understand how to use enable_if
. What I was thinking was that I can enable one or the second one member function from a set of member functions during compilation time but it does not work. Could anyone please explain to me how to do it correctly?
Edited
What I really can't understand is why isn't there typedef
in one of those def. Compiler cannot find it and it wont compile it.
Member functions of class templates (C++ only) You may define a template member function outside of its class template definition. The overloaded addition operator has been defined outside of class X . The statement a + 'z' is equivalent to a. operator+('z') .
Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.
A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.
The term member template refers to both member function templates and nested class templates. Member function templates are function templates that are members of a class or class template. Member functions can be function templates in several contexts.
Here's how it works (note that for convenience I replaced your is_builtin
trait with std::is_arithmetic
and used further C++11 stuff, but it works any way):
template<class T>
struct My
{
template<typename T_ = T, std::enable_if_t<std::is_arithmetic<T_>::value>* = nullptr>
void f(T_ arg)
{
std::cout << "Built-in as a param.\n";
}
template<typename T_ = T, std::enable_if_t<!std::is_arithmetic<T_>::value>* = nullptr>
void f(T_ arg)
{
std::cout << "Non - built-in as a param.\n";
}
};
DEMO
The crucial part is to bring the template parameter into the immediate context by using a default function template parameter T_
which equals the class template parameter T
. For more details, see this question.
You can't use class template parameters to get SFINAE for member functions.
You either need to
make the member function a member function template instead and use enable_if
on the member function template's template parameters or
move the member function f
into a policy class and specialize the class template using enable_if
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With