Why doesn't SFINAE (enable_if) work for member functions of a class template?

放肆的年华 提交于 2019-12-17 07:29:38

问题


#include <type_traits>

struct A{};
struct B{};

template <typename T>
struct Foo
{
    typename std::enable_if<std::is_same<T, A>::value>::type
    bar()
    {}

    typename std::enable_if<std::is_same<T, B>::value>::type
    bar()
    {}
};

Error message:

14:5: error: 'typename std::enable_if<std::is_same<T, B>::value>::type Foo<T>::bar()' cannot be overloaded 10:5: 
error: with 'typename std::enable_if<std::is_same<T, A>::value>::type Foo<T>::bar()'

Source on cpp.sh. I thought both typename std::enable_if<std::is_same<T,?>::value>::type could not be valid at the same time.

Edit

For posterity here is my edit based on @KerrekSB's answer -- SFINAE only works for deduced template arguments

#include <type_traits>

struct A{};
struct B{};

template<typename T>
struct Foo
{
    template<typename U = T>
    typename std::enable_if<std::is_same<U,A>::value>::type
    bar()
    {
    }

    template<typename U = T>
    typename std::enable_if<std::is_same<U,B>::value>::type
    bar()
    {
    }
};

int main()
{
};

回答1:


SFINAE only works for deduced template arguments, i.e. for function templates. In your case, both templates are unconditionally instantiated, and the instantiation fails.

The following variant works:

struct Foo
{
    template <typename T>
    typename std::enable_if<std::is_same<T, A>::value>::type bar(T) {}

    // ... (further similar overloads) ...
};

Now Foo()(x) causes at most one of the overloads to be instantiated, since argument substitution fails in all the other ones.

If you want to stick with your original structure, use explicit class template specialization:

template <typename> struct Foo;

template <> struct Foo<A> { void bar() {} };
template <> struct Foo<B> { void bar() {} };


来源:https://stackoverflow.com/questions/30953248/why-doesnt-sfinae-enable-if-work-for-member-functions-of-a-class-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!