6

这是 C++17 中基于 lambda 的简洁、简洁的折叠表达式:

#include <cstdint>

using ::std::uint64_t;

constexpr auto sumsquares = [](auto... n) { return ((n * n) + ...); };

// I want this to work.
uint64_t foo(uint64_t x, uint64_t y, uint64_t z)
{
    return sumsquares(x, y, z);
}
// And this too
double bar(uint64_t x, double y)
{
    return sumsquares(x, y);
}

我有这段代码是为了在 C++14 中做类似的事情而编写的,但它似乎比它应该的更冗长和混乱。我正在寻找一种以相对清晰和简洁的方式在 C++14 中表达上述 C++17 代码的方法。准确地说,我希望能够编写代码,使用类似函数调用的语法计算某个已知维数的向量的向量幅度的平方。但是,维度的数量可以任意变化。并且坐标系的各个分量的精确数字类型也可能是任意的,并且可能是异构的。但是在 C++14 中处理 C++17 折叠表达式的一般方法是理想的。

#include <cstdint>
#include <utility> 

using ::std::uint64_t;

namespace {
    static constexpr struct {
        template <typename T>
        auto operator()(T && n) const
        {
           return n*n;
        }
        template <typename T, typename... S>
        auto operator()(T && n, S && ... s) const
        {
            return (n * n) + (*this)(::std::forward<S>(s)...);
        }
    } sumsquares;
}

// I want this to work.
uint64_t foo(uint64_t x, uint64_t y, uint64_t z)
{
    return sumsquares(x, y, z);
}
// And this too
double bar(uint64_t x, double y)
{
    return sumsquares(x, y);
}
4

3 回答 3

9
#include <utility>
#include <functional>

template<class F, class A0>
auto fold(F&&, A0&& a0) {
    return std::forward<A0>(a0);
}

template<class F, class A0, class...As>
auto fold(F&& f, A0&&a0, As&&...as) {
    return f(std::forward<A0>(a0), fold(f, std::forward<As>(as)...));
}

auto sum_squares=[](auto&&...args) {
    return fold(std::plus<>{}, (args * args)... );
};
于 2018-06-24T01:12:27.413 回答
6

一种可能的非递归编写方式sum()如下

template <typename ... Ts>
auto sum (Ts ... ts)
 {
   using unused = int[];

   std::common_type_t<Ts...>  ret {};

   (void)unused{ 0, (ret += ts, 0)... };

   return ret;
 }

给定一个sum()函数,sum_of_squares()可以简单写成如下

template <typename ... Ts>
auto sum_of_squares (Ts ... ts)
 { return sum( (ts*ts)... ); }
于 2018-06-24T00:19:11.140 回答
3

是的,您实际上可以通过在多个对象上定义一个通用总和来做更简单和更通用的操作:

template<typename T>
T sum(T x)
{
    return x;
}
template<typename U, typename... T>
auto sum(U x, T... nums)
{
    return x + sum(nums...);
}

template<typename... T>
auto sum_of_squares(T... nums)
{
    auto square = [](auto x) { return x * x; };
    return sum(square(nums)...);
}

现场演示在这里在这里您可以看到生成的程序集(这似乎是最佳的)。虽然我个人非常不喜欢auto作为返回类型,但在这里它允许避免非常复杂的表达式来获取类型。

于 2018-06-24T00:00:43.003 回答