【问题标题】:How to use if constexpr in template fold expressions?如何在模板折叠表达式中使用 if constexpr?
【发布时间】:2018-12-14 17:18:39
【问题描述】:

我想写一个参数数量可变的求和函数,条件是它应该忽略不是std::is_arithmetic的参数

我想出了一个可行的递归版本

auto old_sum(){
    return 0;
}

template<typename T1, typename... T>
auto old_sum(T1 s, T... ts){
    if constexpr(std::is_arithmetic_v<T1>)
        return s + old_sum(ts...);
    else
        return old_sum(ts...);
}

我想知道是否可以在折叠表达式的上下文中使用if constexpr 使以下代码仅考虑参数包中的算术类型:

template<typename... T>
auto fold_sum(T... s){
    return (... + s);
}

【问题讨论】:

    标签: c++ c++17 variadic-templates template-meta-programming fold-expression


    【解决方案1】:

    由于我们没有三元 constexpr 运算符,我们可以使用 lambda 代替。

    #include <type_traits>
    
    template<typename... T>
    constexpr auto fold_sum(T... s){
        return (... + [](auto x)
        {
            if constexpr(std::is_arithmetic_v<T>) return x;
            else return 0;
        }(s));
    }
    

    用法:

    int main()
    {
        static_assert(fold_sum(0, nullptr, 5, nullptr, 11, nullptr) == 16);
    }
    

    live example on godbolt.org

    【讨论】:

    • 你应该给折叠总和的身份来处理空包。
    • 如果你命名 lambda 会更容易阅读 ;-)
    • 这里真的需要else吗?我无法想象if constexpr 会允许在故意滥用时编写无法访问的代码。
    【解决方案2】:

    您绝对想使用if constexpr

    我提出了一个不同的替代方案:std::get()std::pair 来模拟constexpr 三元运算符如下(Vittorio Romeo 的改进;谢谢)

    #include <utility>
    #include <type_traits>
    
    template<typename ... Ts>
    constexpr auto fold_sum (Ts const & ... s)
     { return (... + std::get<std::is_arithmetic_v<Ts>>(std::pair{0, s})); }
    
    int main ()
     {
       static_assert(fold_sum(0, nullptr, 5, nullptr, 11, nullptr) == 16);
     }
    

    【讨论】:

    • 可以通过CTAD简化为std::pair(0, s)
    • @VittorioRomeo - 好主意;我仍然不习惯 C++17 参数推导。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 2018-01-16
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多