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

Является ли это ссылкой для пересылки?

Различие между ссылками rvalue и ссылками на пересылку было достаточно ясно описано в этом примере Скоттом Мейерсом:

Widget&& var1 = someWidget;     // here, "&&" means rvalue reference (1)

auto&& var2 = var1;             // here, "&&" does not mean rvalue reference (2)

template<typename T>
void f(std::vector<T>&& param); // here, "&&" means rvalue reference (3)

template<typename T>
void f(T&& param);              // here, "&&"does not mean rvalue reference (4)

По существу, различие происходит, когда мы имеем выводимый контекст, поэтому случай (3) явно утверждает, что мы имеем vector<...>&&, тогда как T в случае (4) следует вывести и (после применения правил сворачивания ссылок), классифицированных в терминах "категория стоимости".

Но что происходит с более сложным сопоставлением шаблонов? Возьмем следующий пример, например:

template <template <class...> class Tuple, class... Ts>
void f(Tuple<Ts...>&& arg)
{

}

Что означает && здесь?

4b9b3361

Ответ 1

В последнем примере arg является ссылкой rvalue.

Ссылка на пересылку - это ссылка rvalue на параметр cv-unqualified template

и Tuple<Ts...> не является параметром шаблона.

(Цитата из [temp.deduct.call].)

Ответ 2

Это ссылка rvalue, а не ссылка на пересылку.

Самый простой способ быть уверенным в том, чтобы попытаться передать значение lvalue, если оно терпит неудачу, то это ссылка rvalue, если нет, то ссылка на пересылку:

template<typename... Ts>
struct foo {};

//f function definition

int main() {
    foo<int, double> bar;
    f(bar); // fails! Cannot bind lvalue to rvalue reference
    f(foo<int, double>{}); // ok, rvalue is passed
}

Ответ 3

Ссылка на пересылку концепции не является стандартной концепцией, полезно ее распознать, когда вы ее видите, но если вы хотите правильно ее понять и справиться с ней, вы должны понять ссылочную арифметику. (Я считаю, что книга Мейера также гласит об этом)

Что стоит за концепцией ссылки пересылки, является эталонной арифметикой:

  • && & & = &&
  • && и = &
  • && & = &
  • & и = &

Позвольте моделировать вывод типа шаблона компилятора с помощью ссылки пересылки

template<class T>
void foo(T&&);
//...
const int i=42;
foo(i); // the compiler will defines T = const int &
         //          T&&  = const int & && = const int &
         // => the compiler instantiates void foo<const int &>(const int &);
foo(6*7);// the compiler will defines T = int
         //          T&&  = int &&
         // the compiler instantiates  void foo<int>(int &&);

в такой ситуации, создание шаблона foo может производить функция, которая принимает аргумент с помощью ссылки lvalue или функций, которая принимает аргументы rvalue: ссылка перенаправления либо ссылку на rvalue или ссылку на lvalue, в зависимости от вычитания типа шаблона. Он называется так, потому что в такой ситуации параметр должен передаваться либо как lvalue, либо как значение x, и это задание T&& std::forward<T>(T&& a)

Если вы заявляете, что функция имеет:

 template<class T>
 void foo(ATemplateClass<T> && a);

независимо от того, какой тип вывел для T компилятором, вы получите ссылочный параметр rvalue.