How to use SFINAE with nullary member function? [d

2019-07-20 21:12发布

This question already has an answer here:

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?

标签: c++ sfinae
1条回答
爷、活的狠高调
2楼-- · 2019-07-20 22:00

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

查看更多
登录 后发表回答