Here is my somewhat odd code:
template <typename T&>
class A {
public:
void b(typename std::enable_if<!std::is_pointer<T>::value, T>;::type o) {}
void b(typename std::enable_if<std::is_pointer<T>::value, T>;::type o) {}
};
template <typename T>
void b(typename std::enable_if<!std::is_pointer<T>::value, T>::type o) {}
template <typename T>
void b(typename std::enable_if<std::is_pointer<T>::value, T>::type o) {}
If I ifdef out the method b and call b<int *>(pi) where pi is int *, everything compiles.
If I ifdef out the function b (outside class) and call A<int *> a; a.b(pi), I get the following error:
error: no type named 'type' in 'std::__1::enable_if<false, int *>'
Why the inconsistency and how can I fix the problem so that I can use the methods in A?
The problem is, that SFINAE only works during overload resolution and only if the function itself is a template. In your method case, the whole class is a template, meaning that there is no substitution of the template parameter (remember: SFINAE == “Substitution Failure Is Not An Error”).
At the point of instantiation, the method signatures look like this (nevermind the call to them):
To fix this, make the methods templates too:
On a side note, letting the template argument get deduced is the better way to use SFINAE, so you should modify the free functions to look like this:
In C++11, you can even use the template parameters for SFINAE:
Utilizing an alias from the blog entry linked from here: