2013-06-15 2 views
3

Я пытаюсь понять, как lvalues ​​связывают ссылки rvalue. Рассмотрим этот код:lvalue binding to rvalue reference

#include <iostream> 

template<typename T> 
void f(T&& x) { 
    std::cout << x; 
} 

void g(int&& x) { 
    std::cout << x; 
} 

int main() { 
    int x = 4; 
    f(x); 
    g(x); 
    return 0; 
} 

В то время как вызов F() в порядке, вызов г() дает ошибку во время компиляции. Этот вид привязки работает только для шаблонов? Зачем? Можем ли мы как-то это сделать без шаблонов?

ответ

6

С T является аргументом в форме шаблона, T&& становится пересылка-ссылка. Из-за правил сворачивания ссылок f(T& &&) становится f(T&) для lvalues ​​и f(T &&) становится f(T&&) для rvalues.

+0

Это имеет смысл. Но предположим, что мне не нужны шаблоны, тогда есть ли способ получить универсальные ссылки, скажем, в примере выше? Я немного изменил этот вопрос. –

+0

@ r.v Вы можете предоставить вторую перегрузку 'g' для lvalues ​​(' void g (int &) '), или вы можете * переместить * lvalues ​​с помощью' std :: move'. – 0x499602D2

+0

Да, это возможные решения, но я надеялся, что мы получим что-то в строке универсальной ссылки: учитывая тип T (фиксированный, не templated), я могу сопоставлять T & и T && в одном вызове (без перегрузок), а затем использовать пересылку и т. д. Это определенно помогает уменьшить некоторый избыточный код. –

0

0x499602D2 уже ответил на ваш вопрос; тем не менее, следующие изменения в вашем коде могут дать дополнительную информацию.

Я добавил static_assert к f проверить выведенная тип:

#include <type_traits> 

template<typename T> 
void f(T&& x) { 
    static_assert(std::is_same<T&&, int&>::value,""); 
    std::cout << x; 
} 

утверждают, делает не неудачу, поэтому тип x в f в конечном счете int& (в данном конкретном примере).

я изменил, как g называется в main:

g(std::move(x)); 

Теперь код компилируется и программа работает, как ожидалось и печатает 44.

Надеюсь, что это поможет немного понять ссылки на rvalue.

+1

Для этого уже существует шаблон: ['std :: is_rvalue_reference'] (http: // en.cppreference.com/w/cpp/types/is_rvalue_reference) – 0x499602D2

Смежные вопросы