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
и как ее интерпретировать?
Спасибо
Ответы
Ответ 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;