【问题标题】:Applying a function over an arbitrary number of variadic arguments在任意数量的可变参数上应用函数
【发布时间】:2016-04-04 06:48:05
【问题描述】:

这是my previous one 的后续问题。我正在构建一个具有基本矢量数学功能的 Array 类。我想定义一个函数,让用户在整个数组上映射任意函数。我已经可以为预定义的二进制函数执行此操作(例如,operator+= 用于就地添加),但我正在努力了解如何针对任意数量的输入执行此操作。

template<typename T, size_t ... Ns>
class Array
{
public:
    Array() { /* allocate memory of size product(Ns) * sizeof(T) */ }

    ~Array() { /* deallocate memory */ }

    inline Array<T, Ns...>& operator+=(const Array<T, Ns...> &rhs)                   
    {
        // simple case: predefined operation on exactly two Arrays
        T *p1 = data, *p2 = rhs.data;                                                
        while (p1 != data + size) { *p1 += *p2; p1++; p2++; }                                                                            
        return *this;                                                                
    }

    template<class ... Args>
    inline const Array<T, Ns...> map(T (*fn)(arg_type<Args>...), Args ... args)
    {
        // difficult case: arbitrary operations on a variable number of Arrays
    }

    private:
        T *data;
        size_t size;
}

// example usage
double f(double a, double b) { return a + b; }
Array<double,2> x, y, z;
x.map(f, y, z);

我希望这样的东西循环遍历yz 中的所有元素,将f 应用于它们,并将它们存储在x 中。我以为我可以在我的 operator+= 函数上对其进行建模,但我还没有找到可以让我做任何类似事情(和编译)的参数包扩展。

【问题讨论】:

  • 在它的核心,你会说类似(data[I] = f(args[I]...))...,这应该发生在一个辅助函数模板中,它接受index_sequence&lt;I...&gt;Args ...args,我想。
  • data 始终是一维的(即Ns 始终包含单个值)?
  • 用 T 的向量替换数据和大小。编写接受 N 个向量并在所有向量上应用函数的代码,返回结果向量。为您的数组类编写一个带有向量的构造函数。编写这些解决方案,解决您的问题(并停止浪费脑空间来管理原始指针的生命周期!)
  • for (int i = 0; i &lt; Ns; ++i) data[i] = fn(args.data[i]...); 根据描述应该足够了
  • @PiotrSkotnicki 将 i &lt; Ns 替换为 i &lt; product(Ns...)data.resize(product(Ns...));,但基本上是的。

标签: c++ c++11 variadic-templates variadic-functions


【解决方案1】:

这样写:

template<class T, class Array2>
using Array_Size_Copy = // expression that creates a Array<T,???>, where ??? is the Ns... of Array2 above

然后

template<class F, class A0, class...Arrays>
auto array_apply( F&& f, A0&& a0, Arrays&&...arrays ) {
  using R = decay_t<decltype( f(std::declval<A0>().data.front(), std::declval<Arrays>().data.front()...) )>;

  Array_Size_Copy<R, std::decay_t<A0>> retval;

  for (int i = 0; i < a0.size(); ++i) {
    retval.data[i] = f( std::forward<A0>(a0).data[i], std::forward<Arrays>(arrays).data[i]... );
  }
  return retval;
}

添加一些断言(理想情况下为静态断言)所有内容都相同。

上述函数可能需要成为朋友。这意味着您可能必须设置返回值而不是使用auto,但这只是将类型体操移到声明中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    相关资源
    最近更新 更多