2014-07-07 15 views
20

natknąłem się mylący komunikat o błędzie, gdy próbuje zrobić coś tak prostego jakstd :: vector: nie można wiązać 'std :: ostream aka {std :: basic_ostream <char>}' lwartość do 'std :: basic_ostream <char> &&'

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

który mówi

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

(testowane przy użyciu gcc-4.8.1 z -std = C++ 11)

SO podobne pytania jak Overloading operator<<: cannot bind lvalue to ‘std::basic_ostream<char>&&’, która jest o kilka klasa zdefiniowana przez użytkownika z klasami zagnieżdżonymi. Jest też praca wokół zaakceptowanej odpowiedzi na to pytanie.

Ale nie wiem, czy to dotyczy std::vector. Czy ktoś może wyjaśnić, dlaczego ten błąd zdarzył się std::vector i jak go zinterpretować?

Dzięki

Odpowiedz

20

Komunikaty o błędach związanych z szablonami mogą być czasami mylące. Problem polega na tym, że standardowa biblioteka nie definiuje przeciążenia w postaci operator << do wstawiania std::vector (lub jakiegokolwiek innego pojemnika) do std::ostream. Tak więc kompilator nie znalazł odpowiedniego przeciążenia dla operator << i zgłasza tę awarię najlepiej, jak potrafi (która niestety nie jest zbyt dobra/czytelna w twoim przypadku).

Jeśli chcesz przesyłać cały pojemnik, można użyć std::ostream_iterator za to:

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

Jak, dlaczego dostajesz dokładnie ten tajemniczy błąd, pomaga analizować pełny komunikat o błędzie :

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) 
    ^

jest widocznie przeciążenie szablon operator<< który zajmuje argumentu typu std::ostream&& LHS i RHS o argumentów f typ szablonowy; istnieje, aby umożliwić wstawianie do tymczasowych strumieni. Ponieważ jest to szablon, staje się najlepiej dopasowany do wyrażenia w kodzie. Jednak std::cout jest lwartością, więc nie może się połączyć z std::ostream&&. Stąd błąd.

+0

Dzięki za odpowiedź, która wyjaśnia pierwszą część pytania. Dodaję też własny kod do drukowania wektorów. To, czego nie rozumiem (druga część pytania), to sposób, w jaki otrzymujemy tego typu błąd l-ref/r-ref, gdy nie można znaleźć przeciążenia. – tinlyx

+0

@TingL Dodano moje przypuszczenie co do natury błędu. – Angew

+0

To przeciążenie nie jest szczegółem implementacji, ale jest wymagane przez standardowe streszczenie 27.7.1 , aby umożliwić wstawienie do strumienia tymczasowego. Coś jak: 'std :: ofstream (" output.txt ") <<" Cześć tam \ n ";' –

-1

Nie ma zdefiniowanego operator << dla klasy std::vector w klasie std::basic_ostream.

Co chcesz jest następujący

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

Choć może to być napisane prostsze

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

To znany problem z gcc, I filed an enhancement request regarding this.

"jedynym" Problem polega na tym, że rzecz, którą próbujesz wydrukować na konsoli, nie ma numeru operator<<. Niestety komunikat o błędzie nie jest bardzo pomocny. :(

Nawiasem mówiąc, pytanie nie ma nic wspólnego z vector lub referencjami wartości l i wartości r.Minimalny przykład:

#include <iostream> 

struct A { }; 

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

Zobacz dyskusję na prośbę o ulepszenie szczegółów. Krótko mówiąc programiści gcc już próbowali poprawić komunikat o błędzie, ale okazało się to bardzo trudne.

Na co warto, clang's error message z libC++ jest wyraźniejszy moim zdaniem:

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; 
    ~~~~~~~~~^~ 

Tutaj pierwsza linia wyraźnie mówi, na czym polega problem.

+0

Chociaż dane wyjściowe kompilatora mogą być lepsze, zgłaszany błąd ma sens w kontekście standardu. Nie kompiluje się i istnieje przeciążenie, które * prawie * pasuje, z wyjątkiem l-wartości argumentu ... Widzę, że * błąd * bardziej jak prośba o ulepszenie niż prawdziwy błąd. –

+1

@ DavidRodríguez-dribeas Poprawiłem moją odpowiedź i zmieniłem "zgłoszenie błędu" na "prośbę o ulepszenie". To było jedyne miejsce z napisem "bug". Bardzo ważne jest, aby szybko zidentyfikować problem. Kiedy pierwszy raz wpadłem na ten problem, zajęło mi trochę czasu, aby dowiedzieć się, co się dzieje; komunikat o błędzie postawił mnie na niewłaściwym torze. Jak pokazuje to pytanie, nie jestem jedynym, który miał trudności ze zrozumieniem tego komunikatu o błędzie. Cóż, nazwij ten problem prośbą o ulepszenie lub cokolwiek chcesz, nawet programiści gcc przyznają, że to jest problem i próbowali go ulepszyć. Więc to * jest * problemem. – Ali

+0

@ DavidRodríguez-dribeas OK, poprawiłem sformułowanie w kilku miejscach, być może było zbyt silne. Mam nadzieję, że teraz wszystko będzie dobrze, dziękuję za zwrócenie na to mojej uwagi. – Ali