Поведение шаблонной функции C ++

Допустим, у меня есть эта функция:

bool f(int&& one, int&& two) { }

Если я попытаюсь позвонить с этим кодом:

int x = 4;
f(x, 5);

компилятор будет жаловаться, что не может преобразовать x из ссылки lvalue в ссылку rvalue, что является правильным.

Теперь, если я преобразую f в шаблонную функцию следующим образом:

template <class T, class U>
bool f(T&& one, U&& two) { }

тогда я могу назвать это ссылкой lvalue:

int x = 5;
f(x, 5);

Почему это так? Почему компилятор не жалуется в этом случае?

18

Решение

Поскольку существует аргумент шаблона, происходит свертывание ссылок. Это то, что Скотт Мейерс называет универсальные ссылки. U&& на самом деле станет int &, Есть хороший статья и видео о том, как это работает и как это можно использовать.

8

Другие решения

Согласно § 8.3.3 / 6. Это правило свертывания ссылок.

template <class T> void func(T&&)  // Accepts rvalue or lvalue
void func(T&&)                     // Accepts rvalue only
void func(T&)                      // Accepts lvalue only

Стоит привести пример из стандартного проекта:

int i;
typedef int& LRI;
typedef int&& RRI;

LRI& r1 = i;           // r1 has the type int&
const LRI& r2 = i;     // r2 has the type int&
const LRI&& r3 = i;    // r3 has the type int&

RRI& r4 = i;           // r4 has the type int&
RRI&& r5 = 5;          // r5 has the type int&&

decltype(r2)& r6 = i;  // r6 has the type int&
decltype(r2)&& r7 = i; // r7 has the type int&
10

Это происходит из-за правил свертывания ссылок, добавленных в c ++ 11

A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&

В шаблонах эти правила применяются, но не в обычной функции, при этом ссылка не сворачивается в функции. Существуют и другие конкретные ситуации, в которых происходит свертывание ссылок, например, при наличии auto, decltype или typedef (это включает using декларации) Это объясняет результаты вашей компиляции. Свертывание ссылок должно было быть добавлено в c ++ 11, потому что в противном случае использовались бы ссылки типа A & & станет ошибкой, так как вы не можете иметь ссылку на ссылку.

6
По вопросам рекламы [email protected]