Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::vector : cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'

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

like image 612
thor Avatar asked Jul 07 '14 11:07

thor


2 Answers

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.

like image 44
Ali Avatar answered Nov 09 '22 05:11

Ali


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.

like image 71
Angew is no longer proud of SO Avatar answered Nov 09 '22 06:11

Angew is no longer proud of SO