How to use SFINAE with nullary member function? [d

2019-07-20 21:56发布

问题:

This question already has an answer here:

  • Selecting a member function using different enable_if conditions 5 answers

I have a class template Bird with a Boolean template parameter can_fly. Depending on that value, I want to enable a member function with the signature void fly();.

This is my code:

#include <type_traits>

template<bool can_fly>
class Bird {
public:
    template<typename void_t = typename std::enable_if<can_fly>::type>
    void_t fly() { /* ... */ }
};

int main() {
    Bird<true> flyingBird;
    flyingBird.fly();
    Bird<false> flightlessBird;

    return 0;
}

This code compiles fine in Visual Studio 2015, but GCC complains that there is "no type named 'type' in 'struct std::enable_if'" in the third line of main.

I thought the fact that there is no ::type in the false case was the entire point of SFINAE. Can somebody explain to me what I did wrong and what the correct approach is?

回答1:

As mentioned in this answer:

enable_if works because the substitution of a template argument resulted in an error, and so that substitution is dropped from the overload resolution set and only other viable overloads are considered by the compiler.

In your case there is no substitution because can_fly is known at the moment of instantiation. You can create a dummy default bool template parameter to make SFINAE work properly:

template<bool can_fly>
class Bird {
public:
    template<bool X = can_fly, typename = typename std::enable_if<X>::type>
    void fly() { /* ... */ }
};

wandbox example



标签: c++ sfinae