如何在C ++中使用variadic通用lambda计算总和?

时间:2016-12-31 15:31:59

标签: c++ generics lambda c++14 variadic

我想写一个通用的sum函数,如下所示,但不是在模板语法中,而是在lambda语法中:

template<typename T>
auto Sum(T lastSummand)
{
    return lastSummand;
}

template<typename T, typename... Ts>
auto Sum(T firstSummand, Ts... restSummands)
{
    return firstSummand + Sum(restSummands...);
}

因为通用lambda映射到模板,所以应该可以执行以下操作:

auto sum = [](auto firstSummand, auto... restSummands) { ... };

但我无法弄清楚如何使用lambdas进行递归。在这个和其他地方搜索并没有带来多少。

2 个答案:

答案 0 :(得分:4)

在C ++ 14中,你实际上并不需要通过普通lambda来进行递归 例如,您可以这样做:

#include<type_traits>
#include<iostream>

int main() {
    auto l = [](auto... values) {
        std::common_type_t<decltype(values)...> ret = {};
        decltype(ret) _[] = { (ret += values)... };
        (void)_;
        return ret;
    };

    auto v = l(0, 0., 5, 4.2);
    std::cout << v << std::endl;
}

返回类型由给定包的std::common_type_t给出 其余代码包含在等待折叠表达式时常用的常用模式。

在C ++ 17中它将成为:

#include<iostream>

int main() {
    auto l = [](auto... values) { return (values + ...); };
    auto v = l(0, 0., 5, 4.2);
    std::cout << v << std::endl;
}

wandbox上查看。

如果您想在运行中验证给定参数是所有算术类型,您可以使用bool技巧,如下所示:

auto l = [](auto... values) {
    static_assert(
        std::is_same<
            std::integer_sequence<bool, true, std::is_arithmetic<decltype(values)>::value...>,
            std::integer_sequence<bool, std::is_arithmetic<decltype(values)>::value..., true>
        >::value, "!"
    );

    std::common_type_t<decltype(values)...> ret = {};
    decltype(ret) _[] = { (ret += values)... };
    (void)_;
    return ret;
};

答案 1 :(得分:0)

好吧,我假设您需要类似仿函数的类型来计算总和,如果您正在使用lambda。如果是这样,那么我想你可以写一个小的通用类来取代那个lambda。

template < typename T > struct Sum
{
    template < typename U >
    T operator () (U v) const noexcept
    {
        return static_cast< T >(v);
    }

    template < typename U, typename... Values >
    T operator () (U v, Values&&... vs) const noexcept
    {
        return static_cast< T >(v) + (*this)(std::forward< Values >(vs)...);
    }
};

用作:

auto sum = Sum< int >();
printf("%d\n", sum(23, 4.0, true, 7));

我以这样的方式编写它,可以提前指定返回类型。但我想你可以调整它以使其成为通用的。

如果这不是您的意图,请忽略此答案。