3

我正在使用该类型std::valarray<std::valarray<double>>并希望明智地对每个包含的 valarrays 元素求和,以留下std::valarray<double>.

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

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

我的代码:

#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
4

1 回答 1

1

需要为其值类型(在您的情况下为 )定义的sum方法,但还要求它是可默认构造的(来自“数字”概念要求)。这允许该方法在没有 的情况下工作,首先默认构造一个元素,然后添加每个包含的元素。std::valarrayoperator+=std::valarraystd::valarraysumoperator+operator+=

尽管它没有在任何地方定义,但据我所知,它可能像这样工作。

T sum() const {
    T result;
    for (auto& it : elements) {
        result += it;
    }
    return result;
}

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

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

std::accumulate(std::begin(data), std::end(data), std::valarray<double>(data[0].size()))

住在科利鲁。

PS:别问我为什么std::valarray没有方法beginend.

于 2018-02-18T18:23:05.827 回答