GamefanA
GamefanA

Reputation: 1643

SFINAE not working to conditionally compile member function template

I'm trying you use std::enable_if to conditionally choose only one out of two member function template using SFINAE with this code:

#include <iostream>
#include <type_traits>

template<typename T>
struct C {
    template<typename Q = T, typename = typename std::enable_if<std::is_same<Q, int>::value>::type>
    int foo() {
        return 1;
    }

    template<typename Q = T, typename = typename std::enable_if<!std::is_same<Q, int>::value>::type>
    int foo() {
        return 0;
    }

};

int main() {
    std::cout << C<int>().foo() << std::endl;  //error member function foo already defined
}

but for some reason, visual c++ keeps giving me a compiler error that foo is already defined. Even though, it is clear that, depending on the class' template argument, only one function is well-formed. So SFINAE should remove the second one from consideration.

Any idea why this does not work?

Upvotes: 2

Views: 714

Answers (1)

max66
max66

Reputation: 66200

Try with

template<typename T>
struct C {
    template<typename Q = T,
             typename std::enable_if<std::is_same<Q, int>::value, bool>::type = true>
    int foo() { // .............................................^^^^^^^^^^^^^^^^^^^^
        return 1;
    }

    template<typename Q = T, 
             typename std::enable_if<!std::is_same<Q, int>::value, bool>::type = true>
    int foo() { // ..............................................^^^^^^^^^^^^^^^^^^^^
        return 0;
    }

};

the point is that in your code SFINAE will enable/disable default values for template type parameter; but default values do not participate in overload resolution, so, in your case, you have two functions

template<typename, typename = void>
int foo() {
    return 1;
}

template<typename, typename>
int foo() {
    return 0;
}

with the same signature; so the compiler can't choose between the two and will give an error.

The code I proposed is different because in case the test of std::enable_if is false, you don't have the type (the element on the left of the =), not the value. Something as

// ................VVVVVV   what is = true ?
template<typename, = true>
int foo() {
    return 1;
}

that is a true "substitution failure" that disable the method.

Upvotes: 3

Related Questions