Диапазон С++ для цикла по valarray rvalue не работает

Я хотел бы перебирать временную valarray, но она не работает. Вот мой (нерабочий) код:

#include <iostream>
#include <valarray>
int main()
{
        using namespace std;
        valarray<int> numerators = {99, 26, 25};
        valarray<int> denominators = {9, 2, 5};
        for (int i : numerators / denominators) { cout <<  i << ","; }
        // lots of errors
        return 0;
}

Ниже приведен минимальный рабочий пример того, что я хотел бы достичь, за исключением того, что я не хочу определять объект типа temp_array.

#include <iostream>
#include <valarray>
int main()
{
        using namespace std;
        valarray<int> numerators = {99, 26, 25};
        valarray<int> denominators = {9, 2, 5};
        valarray<int> && temp_array = numerators / denominators;
        for (int i : temp_array) { cout << i << ","; }
        // prints 11,13,5,
        return 0;
}

Мой компилятор - g++ версия 4.8.5 (Red Hat 4.8.5-4). Я компилирую флаг -std = С++ 0x.

Я пробовал использовать другой синтаксис, например for (auto&& i : temp_array) и for (int const & i : temp_array), но он не работает.

Ответы

Ответ 1

Как указано в ответе @Yam Marcovivc, результат операции не гарантируется как std::valarray<int>, который может быть передан непосредственно в std::begin(). Временный построенный объект делает трюк:

#include <iostream>
#include <valarray>
int main()
{
        using namespace std;
        valarray<int> numerators = {99, 26, 25};
        valarray<int> denominators = {9, 2, 5};
        for (int i : valarray<int>(numerators / denominators)) { 
            cout <<  i << ","; 
        }
        return 0;
}

См. Live Demo

Ответ 2

Из документации (которая также включает официальный способ сделать это в одном выражении):

В отличие от других функций, которые принимают аргументы std:: valarray, begin() не может принимать типы замещения (например, типы, созданные шаблонами выражений), которые могут быть возвращены из выражений с использованием valarrays: std:: begin (v1 + v2) не переносится, вместо этого следует использовать std:: begin (std:: valarray (v1 + v2)).

Цель этой функции - разрешить диапазон для циклов работать с valarrays, а не предоставлять семантику контейнера.

В зависимости от того, что может быть причиной, есть и это (на что указывает @chris):

[арифметические операторы] могут быть реализованы с использованием типа возврата, отличного от std:: valarray.

Таким образом, технически нечего гарантировать, что возврат может быть безопасно передан на std::begin.

Ответ 3

    for (int i : (valarray<int> &&)(numerators / denominators)) { cout << i << ","; }