【问题标题】:SFINAE with C++14 return type deduction使用 C++14 返回类型推导的 SFINAE
【发布时间】:2014-06-24 21:41:28
【问题描述】:

感谢 C++14,我们很快就能减少冗长的尾随返回类型;例如来自 David Abrahams 2011 post 的通用 min 示例:

template <typename T, typename U>
auto min(T x, U y)
    -> typename std::remove_reference< decltype(x < y ? x : y) >::type
{ return x < y ? x : y; }

C++14下返回类型可以省略,min可以写成:

template <typename T, typename U>
auto min(T x, U y)
{ return x < y ? x : y; }

这是一个简单的例子,但是返回类型推导对于泛型代码非常有用,并且可以避免大量复制。我的问题是,对于这样的功能,我们如何整合 SFINAE 技术?例如,如何使用std::enable_if 来限制我们的min 函数返回整数类型?

【问题讨论】:

    标签: c++ templates sfinae c++14


    【解决方案1】:

    如果您使用返回类型推导,则不能使用返回类型对函数进行 SFINAE。 proposal中提到了这一点

    由于返回类型是通过实例化模板推导出来的,如果实例化格式不正确,则会导致错误而不是替换失败。

    但是,您可以使用额外的未使用的模板参数来执行 SFINAE。

    template <class T, class U>
    auto min1(T x, U y)
    { return x < y ? x : y; }
    
    template <class T, class U,
              class...,
              class = std::enable_if_t<std::is_integral<T>::value &&
                                       std::is_integral<U>::value>>
    auto min2(T x, U y)
    {
        return x < y ? x : y; 
    }
    
    struct foo {};
    
    min1(foo{}, foo{}); // error - invalid operands to <
    min1(10, 20);
    
    min2(foo{}, foo{}); // error - no matching function min2
    min2(10, 20);
    

    Live demo

    【讨论】:

    • 更别提std::is_integal_v了。
    • @0x499602D2 Looks like gcc-4.9 的 libstdc++ 有 enable_if_it。我现在肯定会更频繁地使用它。使用 gcc-4.8 我从来没有使用过它,因为我不想在 clang 和 gcc 之间过多地更改 coliru 的命令行 :)
    • @chris 我无法使用 gcc 或 clang 获取 ::value 的帮助模板来处理 coliru。
    • 我知道 SFINAE 的这种用法,我的建议是 返回类型 将形成 SFINAE 条件 - 而不是参数:对于内置类型,返回类型将是参数之一的类型,但不是用户类型。我也只是以min 为例。不幸的是,推断的返回类型注定要逃避我们的掌握。我相信我们还没有看到尾随返回 decltype 代码复制的结束。
    • @user2023370 不幸的是,这就是您所拥有的返回类型扣除。对于面向用户的函数,我更喜欢带有未使用参数的 SFINAE,而不是返回类型,这样他们就不必通过 decltypeenable_if 表达式来找出类型是什么,但你可以争论这就是文档的用途。无论如何,提供明确的第三个模板参数的人有一个解决方案......更多未使用的参数:) 查看更新的答案;添加参数包后,您将无法为执行 SFINAE 的参数提供参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 2015-03-05
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多