cannot bind ‘T’ lvalue to ‘T&&’

180
23 августа 2017, 18:13

Почему я не могу сделать так?

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
template <class Type, template <class, class = std::allocator<Type> > class Container>
void print_container(Container<Type>&& container, ostream& os) {
    os << "{ ";
    for (auto& var : container) {
        os << var << " ";
    }
    os << "}";
}
int main(int argc, char* argv[])
{
    std::vector<string> name;
    name.push_back("Igor");
    name.push_back("Andrii");
    print_container(name, cout);
    //print_container(vector<string>{"Igor", "Andrii"}, cout); // Работает без ошибок
    return 0;
}

Получаю ошибки:

example.cpp:22:31: error: cannot bind std::vector<std::basic_string<char> >’ lvalue to std::vector<std::basic_string<char> >&&’
     print_container(name, cout);
                               ^
example.cpp:8:6: note: initializing argument 1 of void print_container(Container<Type>&&, std::ostream&) [with Type = std::basic_string<char>; Container = std::vector; std::ostream = std::basic_ostream<char>]’
 void print_container(Container<Type>&& container, ostream& os) {
Answer 1

напишите

print_container(std::move(name), cout);

да и по-хорошему print_container константную ссылку должна принимать, а не r-value refenece... хотя не, тут универсальная ссылка, так что норм... хотя не все-таки r-value(увидев другой ответ)

Answer 2

Проблема в Вашем коде в том, что шаблонные шаблонные параметры не дают на выходе пробрасывающую ссылку (forwarding reference). Но, судя по всему, Вы пытаетесь её использовать без понимания зачем она нужна, т.к. в Вашем примере нет никакого кода, который бы подразумевал пробрасывание типа.

Из-за вышеописанной проблемы у Вас получается функция, которая первым параметром принимает rvalue-ссылку, но Вы передаёте туда lvalue-объект, поэтому компилятор ругается. Правильным выходом в этой конкретной ситуации будет использование const Container<Type>& container в качестве аргумента функции. Ведь Вы не меняете контейнер и не передаёте его никуда: другие варианты здесь просто избыточны.

Но если отвлечься от всего вышесказанного, то можно заметить ещё одно: Вам совершенно не нужен шаблонный шаблонный параметр, ведь Вы нигде не используете то, что вывели благодаря ему! Поэтому если переписать пример так:

template <typename Container>
void print_container(Container&& container, ostream& os) {
    os << "{ ";
    for (auto& var : container) {
        os << var << " ";
    }
    os << "}";
}

, то он станет

  1. Проще.
  2. Имеющим пробрасывающую ссылку (хотя она и не нужна).

Код из вопроса позволил найти баг в MSVC.

READ ALSO
Контейнер deque в STL c++

Контейнер deque в STL c++

Я начал изучения библиотеки STL и нашел такой интересный контейнер, как deque, но я не понял, в чем его преимущество, если можно заменить его другими...

406
установить программу на удалённой windows машине

установить программу на удалённой windows машине

Добрый день! Не могу сообразить как загуглить даже) Подскажите пожалуйста в каком направлении копать? Хочу в доменной сети (может это и не важно)...

227
функции push и pop [требует правки]

функции push и pop [требует правки]

stack кто знает как написать рабочие функции push и pop для работы со stack?

211
Проблема с методами begin и end

Проблема с методами begin и end

После компиляции выводит: 1 1

215