成员函数中的C ++ SFINAE enable_if_t,如何消除歧义?

时间:2018-08-29 18:19:06

标签: c++ c++11 templates sfinae enable-if

假设我们有一些SFINAE成员函数:

class foo{
    template <class S, class = std::enable_if_t<std::is_integral<S>::value, S>
    void bar(S&& s);
    template <class S, class = std::enable_if_t<!std::is_integral<S>::value, S>
    void bar(S&& s);
}

如果我们如上所述声明它,那么如何定义它们?它们的两个功能签名都看起来像:

template <class S, class>
inline void foo::bar(S&& s){ ... do something ... }

我看到了一些示例,其中一个示例返回一个std::enable_if_t<...>

template <class S, class>
auto bar(S&& s) -> std::enable_if_t<!std::is_integral<S>::value, S>(...){
    ... do something ...
}

根据返回类型进行歧义消除。但是我不想退回任何东西。

3 个答案:

答案 0 :(得分:9)

由于默认参数不是函数签名的一部分,因此请使其不默认

class foo{
    template <class S, typename std::enable_if<std::is_integral<S>::value, int>::type = 0>
    void bar(S&& s);
    template <class S, typename std::enable_if<!std::is_integral<S>::value, int>::type = 0>
    void bar(S&& s);
};

Live Demo


编辑:根据普遍的需求,这是C ++ 17中的相同代码:

class foo{
public:
    template <class S>
    void bar(S&& s)
    {
        if constexpr(std::is_integral_v<S>)
            std::cout << "is integral\n";
        else
            std::cout << "NOT integral\n";
    }
};

constexpr if语句对于编译器来说是特殊的,因为该分支是在编译时选择的,并且未使用的分支甚至都没有实例化

C++17 Demo

答案 1 :(得分:5)

对于C ++ 11编译器,另一种选择是使用标签分配。

template <class S>
void bar(S&& s)
{
    bar(std::forward<S>(s), std::is_integral<S>{});
}

template <class S>
void bar(S&& s, std::true_type)
{
    ... 
}

template <class S>
void bar(S&& s, std::false_type)
{
    ... 
}

答案 2 :(得分:5)

您仍然可以在返回类型中执行此操作。只需保留默认值enable_if(即void)即可。即使您只使用C ++ 11,也只需添加以下别名:

template <bool B, typename T=void>
using enable_if_t = typename std::enable_if<B, T>::type;

然后您可以这样做:

template <class S>
enable_if_t<std::is_integral<S>::value>
bar(S);

template <class S>
enable_if_t<!std::is_integral<S>::value>
bar(S);

或者:

template <class S>
auto bar(S) -> enable_if_t<std::is_integral<S>::value>

template <class S>
auto bar(S) -> enable_if_t<!std::is_integral<S>::value>

无论哪种方式,您都有两个经过正确区分的函数,它们返回void