enable_if seems to work outside a class but not inside

c++, c++11, sfinae, templates

Solution

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):

void A<int*>::b(std::enable_if<false, int*>::type o) // error
void A<int*>::b(std::enable_if<true, int*>::type o)

To fix this, make the methods templates too:

template<class T>
class A{
public:
  template<class U>
  void b(U o, typename std::enable_if<!std::is_pointer<U>::value>::type* = 0){}
  // same for the other version
};

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:

template<class T>
void b(T o, typename std::enable_if<!std::is_pointer<T>::value>::type* = 0){}
// same for the other version

In C++11, you can even use the template parameters for SFINAE:

template<class T, EnableIf<std::is_pointer<T>> = {}>
void b(T o);

Utilizing an alias from the blog entry linked from here:

namespace detail{ enum class enabler{}; }

template<class Cond, class T = detail::enabler>
using EnableIf = typename std::enable_if<C::value, T>::type;

Problem

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?

Original source

Related problems