Я играл с 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;
Эта функция может быть реализована только для типа T, для которого оператор += можно применять.Эта функция возвращает сумму всех элементов массива.Если массив имеет длину 0, поведение не определено.Если массив имеет длину 1, sum () возвращает значение элемента 0. В противном случае возвращаемое значение вычисляется путем применения оператора + = к копии элемента массива и всех других элементов массива в неопределенном порядке.
valarray имеет оператор + =
Так что я ожидаю, что 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
, но вместо инициализации __r
первым элементом в valarray он создается по умолчанию.Конструктор по умолчанию для valarray создает массив размера 0. Итак, окончательный результат по-прежнему остается valarray размера 0.
Верно ли мое понимание стандарта (и в glibcxx STL есть ошибка)?Или я должен быть исправлен?
Для записи я использую g ++ 7.3.0 под Cygwin, но он воспроизводится на coliru, который, вероятно, не работает под Cygwin ...