在std :: valarray <t>上使用.sum()和+ =

时间:2018-02-18 17:26:06

标签: c++11 stl containers valarray

我使用的是std::valarray<std::valarray<double>>类型,并且希望对每个包含的valarrays元素进行求和,以留下std::valarray<double>

C ++文档声明运算符.sum()可以应用于std::valarray<T>,只要为类型T定义了运算符+=。我的代码(方法1)尝试将此应用于std::valarray<std::valarray<double>>,但结果似乎是无稽之谈。

但是如果我手动执行此操作,使用+=运算符(method2),我会得到我想要的结果。但是,method2的工作原理似乎意味着使用.sum()为类型+=定义了运算符std::valarray<double>,因此定义了该方法1。应该管用。我真的无法理解这里发生的事情......

我的代码:

#include <iostream>
#include <valarray>

// Attempt to use .sum() operator
std::valarray<double> method1(const std::valarray<std::valarray<double>>& data) {
  return data.sum();
}

// Manual summation using += operator
std::valarray<double> method2(const std::valarray<std::valarray<double>>& data) {
  std::valarray<double> sum(data[0].size());
  for (size_t i{0}; i < data.size(); i++) {
    sum += data[i];
  }
  return sum;
}

// Display size and elements
void showData(const std::valarray<double> data) {
  std::cout << "Size = " << data.size() << "\n";
  std::cout << "Data = ";
  for (size_t i{0}; i < data.size(); i++) {
    std::cout << data[i] << " ";
  }
  std::cout << "\n\n";
}

int main() {
  std::valarray<std::valarray<double>> data{{1,2},{3,4}};  
  showData(method1(data));
  showData(method2(data));
}

我的输出:

Size = 0
Data = 

Size = 2
Data = 4 6

1 个答案:

答案 0 :(得分:1)

sum std::valarray方法需要为其值类型定义operator+=(在您的情况下为std::valarray),但std::valarray也需要sum默认构造(来自&#34; Numeric&#34;概念要求)。 这允许operator+方法在没有operator+=的情况下工作,首先默认构造一个元素,然后使用T sum() const { T result; for (auto& it : elements) { result += it; } return result; } 添加每个包含的元素。

虽然它没有在任何地方定义,据我所知,它可能会像这样。

std::valarray<std::valarray>

valarray(operator+=)的valarray的问题是默认构造的valarray是空的。当std::accumulate(std::begin(data), std::end(data), std::valarray<double>(data[0].size())) 应用空的valarray和非空的valarray时,会导致未定义的行为("The behavior is undefined if size() != v.size()")。你可能得到的结果是一个空的valarray(但你可能得到任何东西)。

您可以使用的是std::accumulate。它需要一个初始值作为第三个参数,它可以解决问题。

std::valarray

Live on Coliru.

PS:不要问我为什么begin没有方法end和{{1}}。