如何在模板折叠表达式中使用constexpr?

时间:2018-12-14 17:18:40

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

我想编写一个具有可变数量参数的sum函数,条件是它应该忽略不是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);
}

2 个答案:

答案 0 :(得分:9)

由于我们没有三元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

答案 1 :(得分:3)

您绝对要使用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);
 }