2014-07-07 12 views
20

ho incontrato un messaggio di errore di confusione quando si cerca di fare qualcosa di semplice comestd :: vector: non si può legare 'std :: ostream {alias std :: basic_ostream <char>}' lvalue a 'std :: basic_ostream <char> &&'

std::cout << std::vector<int>{1,2,3}; 

che dice

cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&' 
int main() { std::cout << std::vector<int>{1,2,3}; } 

(testato con gcc-4.8.1 con -std = C++ 11)

ha così domande simili come Overloading operator<<: cannot bind lvalue to ‘std::basic_ostream<char>&&’, che è di circa un po ' classe definita dall'utente con classi nidificate. C'è anche un lavoro attorno alla risposta accettata a questa domanda.

Ma non so se questo si applica a std::vector. Qualcuno può spiegare perché questo errore si verifica a std::vector e come interpretarlo?

Grazie

risposta

20

I messaggi di errore relativi ai modelli possono confondere a volte. Il problema è che la libreria standard non definisce un sovraccarico di operator << per l'inserimento di std::vector (o qualsiasi altro contenitore, per quella materia) in un std::ostream. Quindi il compilatore non riesce a trovare un sovraccarico adatto per operator << e segnala questo errore nel miglior modo possibile (che purtroppo non è troppo buono/leggibile nel tuo caso).

Se si desidera eseguire lo streaming di un intero contenitore, è possibile utilizzare std::ostream_iterator per questo:

auto v = std::vector<int>{1, 2, 3}; 
std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, " ")); 

quanto riguarda il motivo che stai ricevendo esattamente questo errore criptico, aiuta ad analizzare il messaggio di errore completo :

prog.cpp: In function ‘int main()’: 
prog.cpp:13:37: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’ 
    std::cout << std::vector<int>{1,2,3}; 
            ^
In file included from /usr/include/c++/4.8/iostream:39:0, 
       from prog.cpp:3: 
/usr/include/c++/4.8/ostream:602:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::vector<int>]’ 
    operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) 
    ^

C'è evidentemente un sovraccarico del modello di operator<< che prende un argomento di tipo ss std::ostream&& e un argomento RHS o f il tipo di modello; esiste per consentire l'inserimento in flussi temporanei. Dal momento che è un modello, diventa la migliore corrispondenza per l'espressione nel codice. Tuttavia, std::cout è un lvalue, quindi non può essere associato a std::ostream&&. Quindi l'errore.

+0

Grazie per la risposta, che spiega la prima parte della domanda. Rotolo il mio codice per stampare anche i vettori. Quello che non capisco (seconda parte della domanda) è come otteniamo questo tipo di errore l-ref/r-ref quando non è possibile trovare un sovraccarico. – tinlyx

+0

@TingL Aggiunta la mia ipotesi sulla natura dell'errore. – Angew

+0

Questo overload non è un dettaglio di implementazione, ma richiesto dalla sinossi standard 27.7.1 , per consentire l'inserimento in un flusso temporaneo. Qualcosa come: 'std :: ofstream (" output.txt ") <<" Ciao \ n ";' –

-1

Non è definito operator << per la classe std::vector nella classe std::basic_ostream.

Quello che vogliamo è la seguente

for (int x : std::vector<int> { 1, 2, 3 }) std::cout << x << ' '; 
std::cout << std::endl; 

Anche se può essere scritto più semplice

for (int x : { 1, 2, 3 }) std::cout << x << ' '; 
std::cout << std::endl; 
8

Questo è un problema noto con gcc, I filed an enhancement request regarding this.

Il "solo" problema è che il cosa stai cercando di stampare sulla console non ha operator<<. Sfortunatamente, il messaggio di errore non è molto utile. :(

A proposito, la domanda non ha nulla a che fare con vector o riferimenti di valore-l e valore-r.Un esempio minimo:

#include <iostream> 

struct A { }; 

int main() { 
    A a; 
    std::cout << a; 
} 

Vedere la discussione alla richiesta di miglioramento per i dettagli cruenti. In breve, gli sviluppatori di gcc avevano già provato a migliorare il messaggio di errore, ma si è dimostrato notoriamente difficile.

Per quello che vale, clang's error message con ++ libc è più chiara a mio parere:

clang++ -std=c++11 -stdlib=libc++ -lc++abi main.cpp && ./a.out 
main.cpp:7:15: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'A') 
    std::cout << a; 
    ~~~~~~~~~^~ 

Qui, la prima linea dice chiaramente qual è il problema.

+0

Mentre l'output dal compilatore potrebbe essere migliore, l'errore riportato ha tutto il senso nel contesto dello standard. Non riesce a compilare e c'è un sovraccarico che * quasi * corrisponde eccetto per l'lvalue-ness dell'argomento ... Vedo che * bug * somiglia più a una richiesta di miglioramento che a un bug reale. –

+1

@ DavidRodríguez-dribeas Ho rivisto la mia risposta e cambiato "segnalazione bug" a "richiesta di miglioramento". Quello era l'unico posto che diceva "bug". Per me è molto importante identificare rapidamente il problema. Quando mi sono imbattuto per la prima volta in questo problema, mi ci è voluto un po 'di tempo per capire cosa sta succedendo; il messaggio di errore mi ha messo sulla strada sbagliata. Come dimostra questa domanda, non sono l'unico ad aver avuto difficoltà a comprendere quel messaggio di errore. Bene, chiama questo problema una richiesta di miglioramento o qualunque cosa tu voglia, anche gli sviluppatori di gcc ammettono che questo è un problema e hanno provato a migliorarlo. Quindi * è * un problema. – Ali

+0

@ DavidRodríguez-dribeas OK, ho rivisto la formulazione in diversi punti, forse era troppo forte. Spero che lo troverai OK ora, grazie per attirare la mia attenzione su di esso. – Ali

Problemi correlati