3

This Code failed to compile in VS2013.

template<typename T>
class SomeClass {
public:
    std::enable_if_t<std::is_fundamental<T>::value, T>
        DoSomething() {
        return T();
    }

    std::enable_if_t<!std::is_fundamental<T>::value, T>
        DoSomething() {
        return T();
    }
};

How to make it work in VS2013(DoSomething must be non-static member function)?

blah
  • 31
  • 4

3 Answers3

3

SFINAE only works on templates. Your DoSomething() is not a template, it's a non-template member of a class template. You need to make it a template:

template<typename T>
class SomeClass {
public:
    template <class U = T>
    std::enable_if_t<std::is_fundamental<U>::value, T>
        DoSomething() {
        return T();
    }

    template <class U = T>
    std::enable_if_t<!std::is_fundamental<U>::value, T>
        DoSomething() {
        return T();
    }
};

[Live example]

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
2

From here

Only the failures in the types and expressions in the immediate context of the function type or its template parameter types are SFINAE errors.

To get SFINAE in the resolution of DoSomething, you need to introduce an immediate context via another template parameter and check that it is T.

template<typename T>
class SomeClass {
public:
    template <typename U = T> 
    std::enable_if_t<std::is_fundamental<U>::value && std::is_same<U,T>::value, T>
        DoSomething() {
        return T();
    }

    template <typename U = T> 
    std::enable_if_t<!std::is_fundamental<U>::value && std::is_same<U,T>::value, T>
        DoSomething() {
        return T();
    }
};

The std::is_same check is added to prevent someone calling SomeClass::DoSomething<U> with U being a type that isn't T.

Community
  • 1
  • 1
Pradhan
  • 16,391
  • 3
  • 44
  • 59
2

Tag dispatch feels better and cleaner than SFINAE for this:

template<typename T>
class SomeClass {
private:
    T DoSomethingImpl(std::true_type /*is_fundamental*/) { return T(); }
    T DoSomethingImpl(std::false_type /*is_fundamental*/) { return T(); }
public:
    T DoSomething() {
        return DoSomethingImpl(std::is_fundamental<T>());
    }
};
T.C.
  • 133,968
  • 17
  • 288
  • 421