I encountered a confusing error message when trying to do something as simple as
std::cout << std::vector<int>{1,2,3};
which says
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}; }
(tested using gcc-4.8.1 with -std=c++11)
SO has similar questions like Overloading operator<<: cannot bind lvalue to ‘std::basic_ostream<char>&&’, which is about some user defined class with nested classes. There is also a work around the accepted answer to that question.
But I don't know whether this applies to std::vector
. Can someone explain why this error happens to std::vector
, and how to interpret it?
Thanks
This a known issue with gcc, I filed an enhancement request regarding this.
The "only" problem is that the thing you are trying to print out to the console has no operator<<
. Unfortunately, the error message is not very helpful. :(
By the way, the question has nothing to do with vector
or l-value and r-value references. A minimal example:
#include <iostream>
struct A { };
int main() {
A a;
std::cout << a;
}
See the discussion at the enhancement request for the gory details. In short, the gcc developers had already tried to improve the error message but it proved to be notoriously difficult.
For what it is worth, clang's error message with libc++ is clearer in my opinion:
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;
~~~~~~~~~ ^ ~
Here, the first line clearly says what the problem is.
Template-related error messages can be confusing at times. The problem is that the standard library does not define an overload of operator <<
for inserting std::vector
(or any other container, for that matter) into a std::ostream
. So the compiler fails to find a suitable overload for operator <<
, and reports this failure as best as it's able (which is unfortunately not too good/readable in your case).
If you want to stream an entire container, you can use std::ostream_iterator
for that:
auto v = std::vector<int>{1, 2, 3};
std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, " "));
As for why you're getting precisely this cryptic error, it helps to analyse the full error message:
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)
^
There is apparently a template overload of operator<<
which takes a lhs argument of type std::ostream&&
and a rhs argument of the templated type; it exists to allow insertion into temporary streams. Since it's a template, it becomes the best match for the expression in your code. However, std::cout
is an lvalue, so it cannot bind to std::ostream&&
. Hence the error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With