2016-01-28 15 views
15

Vorrei eseguire un'iterazione su un valarray temporaneo, ma non funziona. Qui è il mio (non funzionante) Codice:C++ range-based for loop over valarray rvalue non funziona

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

Di seguito è riportato un esempio di lavoro minima di quello che vorrei realizzare, se non che io non voglio definire un oggetto come 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; 
} 

Il mio compilatore è g ++ versione 4.8.5 (Red Hat 4.8.5-4). Sto compilando con il flag -std = C++ 0x.

Ho provato altre sintassi come for (auto&& i : temp_array) e for (int const & i : temp_array), ma non funziona.

+2

'' operatore di valarray'/'è permesso di tornare un proxy oggetto alla modelli di espressione. – chris

+0

Sono stato lontano da C++ per troppo tempo, apparentemente. Qualcuno potrebbe spiegare come 'for (int i: temp_array) {}' è un'istruzione loop valida? Non dovrebbe essere qualcosa come 'for (init; end_condition; incrementare)'? – user1717828

+0

@ user1717828 Vedere loop basato su intervallo di C++ 11. – milleniumbug

risposta

11

Come sottolineato @Yam Marcovivc's answer il risultato dell'operazione non è sempre garantito un std::valarray<int> che può essere passata direttamente a std::begin(). Un oggetto costruito temporanea fa il trucco:

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

Consulta l'Live Demo

18

Dalla documentazione (che comprende anche il mezzo ufficiale per fare questo in una sola espressione):

A differenza di altre funzioni che accettano argomenti std :: valarray, begin() non può accettare il tipo di sostituzione (ad esempio come i tipi prodotti dai modelli di espressione) che possono essere restituiti da espressioni che coinvolgono valarray: std :: begin (v1 + v2) non è portabile, std :: begin (std :: valarray (v1 + v2)) deve essere usato anziché.

L'intento di questa funzione è di consentire all'intervallo di cicli di funzionare con valarrays, non di fornire semantica del contenitore.

Quanto a quello che potrebbe essere il motivo, c'è anche questo (che è stato segnalato da @ Chris):

[operatori aritmetici] possono essere implementati con il tipo di ritorno diverso da std :: valarray .

Quindi non c'è tecnicamente nulla che garantisca che i resi possano essere trasferiti in modo sicuro a std::begin.

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

Funziona, ma raccomandare calchi in stile c potrebbe non essere il miglior consiglio. Inoltre, solo la pubblicazione di codice senza ulteriori spiegazioni (e riferendosi ad altre risposte) non rende questa una grande risposta. –