2016-01-28 42 views
15

Chciałbym iterować nad tymczasową valarray, ale to nie działa. Oto mój (bez pracy) Kod:C++ w oparciu o zakres dla pętli nad wartością valarray nie działa

#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; 
} 

Poniżej jest przykład minimalny pracy, co chciałbym osiągnąć, oprócz tego, że nie chcę, aby określić przedmiot jak 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; 
} 

Mój kompilator jest w wersji g ++ 4.8.5 (Red Hat 4.8.5-4). Kompiluję się z flagą -std = C++ 0x.

Próbowałem innych składni, takich jak for (auto&& i : temp_array) i for (int const & i : temp_array), ale to nie działa.

+2

'valarray' za' operator/'może powrócić proxy obiekt a la szablony ekspresji. – chris

+0

Najwyraźniej nie było mnie zbyt długo w C++. Czy ktoś mógłby wyjaśnić, w jaki sposób 'for (int i: temp_array) {}' jest poprawną instrukcją pętli for? Czy nie powinno to być coś takiego jak 'for (init; end_condition; increment)'? – user1717828

+0

@ user1717828 Zobacz pętlę C++ 11 dla zasięgu. – milleniumbug

Odpowiedz

11

Jak wskazano w @Yam Marcovivc's answer wynik operacji nie jest gwarantowana być std::valarray<int>, które mogą być przekazywane bezpośrednio do std::begin(). Tymczasowy zbudowany obiekt załatwia sprawę:

#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; 
} 

zobaczyć Live Demo

18

Z dokumentacji (która obejmuje również oficjalny sposób to zrobić w jednym wyrażeniu):

przeciwieństwie do innych funkcji, które przyjmują argumenty std :: valarray, begin() nie może zaakceptować typy zastępczych (takich jako typy generowane przez szablony ekspresji), które mogą być zwracane z wyrażeń obejmujących valarrays: std :: begin (v1 + v2) nie jest przenośny, std :: begin (std :: valarray (v1 + v2)) musi być użyty zamiast.

Celem tej funkcji jest zezwolenie zakresowi pętli na pracę z valarrays, a nie zapewnienie semantyki kontenera.

Co do tego, co może być powodem, jest również to (co zostało wskazane przez @chris):

[operatory arytmetyczne] mogą być realizowane ze zwracanego typu różni się od std :: valarray .

Więc jest technicznie nic zagwarantować, że co zwraca mogą być bezpiecznie przenoszone na std::begin.

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

Działa, ale polecanie rzutów w stylu c może nie być najlepszą radą. Również umieszczanie kodu bez żadnych dodatkowych wyjaśnień (i czy odnosi się to do innych odpowiedzi) nie sprawia, że ​​jest to świetna odpowiedź. –