gpt4 book ai didi

c++ - glibcxx STL 在其 std::valarray::sum() 的实现中是否不正确?

转载 作者:可可西里 更新时间:2023-11-01 16:39:46 27 4
gpt4 key购买 nike

我在玩弄valarrays当我碰到某些东西时,我认为是编译器的 STL 实现中的错误。这是我可以制作的最小示例:

#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <valarray>

using namespace std;

int main()
{
valarray<int> Y(0xf00d, 1);
valarray<valarray<int>> X(Y, 1);
cout << "Y[0] = " << std::hex << Y[0] << '\n';
cout << "X[0][0] = " << std::hex << X[0][0] << '\n';
cout << "X[0].size() = " << X[0].size() << '\n';
cout << "X.sum().size() = " << X.sum().size() << '\n';
}

这将输出:

$ g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Y[0] = f00d
X[0][0] = f00d
X[0].size() = 1
X.sum().size() = 0

您可以在coliru 编译并运行它

为什么我认为这是一个错误?因为按照标准(26.6.2.8)

T sum() const;

This function may only be instantiated for a type T to which operator+= can be applied. This function returns the sum of all the elements of the array. If the array has length 0, the behavior is undefined. If the array has length 1, sum() returns the value of element 0. Otherwise, the returned value is calculated by applying operator+= to a copy of an element of the array and all other elements of the array in an unspecified order.

valarray 确实有一个 += operator

所以我希望 X.sum()X[0] 具有相同的值。但显然不是这样,因为它的大小是 0 而不是 1。

我查看了 sum() 的实现并将其追溯到这段代码:

  //
// Compute the sum of elements in range [__f, __l)
// This is a naive algorithm. It suffers from cancelling.
// In the future try to specialize
// for _Tp = float, double, long double using a more accurate
// algorithm.
//
template<typename _Tp>
inline _Tp
__valarray_sum(const _Tp* __f, const _Tp* __l)
{
_Tp __r = _Tp();
while (__f != __l)
__r += *__f++;
return __r;
}

我们知道问题出在哪里。代码将总和累加到 __r 中,但不是用 valarray 中的第一项初始化 __r,而是默认构造它。 valarray 的默认构造函数创建一个大小为 0 的数组。因此最终结果仍然是一个大小为 0 的 valarray。

我对标准的理解是否有效(并且 glibcxx STL 有错误)?还是应该纠正?

郑重声明,我在 cygwin 下使用 g++ 7.3.0,但它是在 coliru 上复制的,它可能没有在 cygwin 下运行...

最佳答案

这对我来说是一个错误。 sum()

Requires: size() > 0. This function may only be instantiated for a type T to which operator+= can be applied.

valarray 确实有一个 operator += 所以它符合条件。这是operator +=

Requires: size() == v.size(). Each of these operators may only be instantiated for a type T if the indicated operator can be applied to two operands of type T. The value of an element in the left-hand side of a valarray compound assignment operator does not depend on the value of another element in that left hand side.

所以通过执行 _Tp __r = _Tp(); 他们生成一个 valarraysize() 不等于元素的大小因此它不能与它的 operator += 一起使用。更正确的实现方式是

  template<typename _Tp>
inline _Tp
__valarray_sum(const _Tp* __f, const _Tp* __l)
{
_Tp __r = *__f++; // this is okay as the function is requires size > 0. It is the users responsibility to make sure that is the case
while (__f != __l)
__r += *__f++;
return __r;
}

关于c++ - glibcxx STL 在其 std::valarray::sum() 的实现中是否不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52861540/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com