Подтвердить что ты не робот

Std::vector: невозможно привязать 'std:: ostream {aka std:: basic_ostream <char>}' lvalue to 'std:: basic_ostream <char> &&'

Я столкнулся с запутанным сообщением об ошибке при попытке сделать что-то так же просто, как

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

в котором говорится

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

(проверено с использованием gcc-4.8.1 с -std = С++ 11)

SO имеет похожие вопросы, такие как Оператор перегрузки <: не может связывать lvalue с 'std:: basic_ostream <char> &&, который является о некотором определенном пользователем классе с вложенными классами. Существует также работа вокруг принятого ответа на этот вопрос.

Но я не знаю, относится ли это к std::vector. Может ли кто-нибудь объяснить, почему эта ошибка происходит с std::vector и как ее интерпретировать?

Спасибо

4b9b3361

Ответ 1

Сообщения об ошибках, связанные с шаблоном, могут иногда вводить в заблуждение. Проблема в том, что стандартная библиотека не определяет перегрузку operator << для вставки std::vector (или любого другого контейнера, если на то пошло) в std::ostream. Поэтому компилятор не может найти подходящую перегрузку для operator << и сообщает об этом сбое как можно лучше (что, к сожалению, не слишком хорошо/читаемо в вашем случае).

Если вы хотите передать весь контейнер, вы можете использовать std::ostream_iterator для этого:

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

Что касается того, почему вы получаете именно эту загадочную ошибку, это помогает проанализировать полное сообщение об ошибке:

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

По-видимому, существует перегрузка шаблона operator<<, которая принимает аргумент lhs типа std::ostream&& и аргумент rhs шаблонного типа; он существует, чтобы разрешить вставку во временные потоки. Поскольку это шаблон, он становится лучшим совпадением для выражения в вашем коде. Однако std::cout является lvalue, поэтому он не может привязываться к std::ostream&&. Отсюда ошибка.

Ответ 2

Это известная проблема с gcc, Я подал запрос об улучшении.

Проблема "только" состоит в том, что вещь, которую вы пытаетесь распечатать на консоли, не имеет operator<<. К сожалению, сообщение об ошибке не очень полезно.: (

Кстати, вопрос не имеет ничего общего с ссылками vector или l-value и r-value. Минимальный пример:

#include <iostream>

struct A { };

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

См. обсуждение в запросе расширения для деталей gory. Короче говоря, разработчики gcc уже пытались улучшить сообщение об ошибке, но оказалось, что это было трудно.

Для чего стоит сообщение об ошибке clang с libС++ яснее, на мой взгляд:

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

Здесь первая строка четко говорит о том, в чем проблема.

Ответ 3

В классе std::basic_ostream нет класса operator << для класса std::vector.

Что вы хотите, это следующее

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

Хотя его можно написать проще

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