Ссылка на значение l удержания шаблона функции и универсальная ссылка - PullRequest
0 голосов
/ 06 ноября 2018

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

template <typename Buf>
void copy(
    Buf&& input_buffer,
    Buf& output_buffer) 
{}

, в котором input_buffer является универсальной ссылкой, а output_buffer является ссылкой l-значения.

Reference collapsing rules убедитесь, что input_buffer действительно, независимо от выводимого типа Buf, универсальной ссылки, а output_buffer действительно является ссылкой l-значения.

Однако мне интересно, как здесь выводится тип Buf.

Я обнаружил, что copy передается r-значение как input_buffer, (и l-значение как output_buffer, очевидно) Buf является не ссылочным типом.

Однако, если я передам два l-значения, программа не скомпилируется:

int i = 4;
int j = 6;

_copy(i, j);

Я ожидаю, что компилятор выведет Buf в int&. Следуя правилам свертывания ссылок, я бы ожидал, что input_buffer станет ссылкой на l-значение, то есть & + && -> & и output_buffer тоже станут ссылкой на l-значение; & + & -> &.

Итак, вопрос: почему этот код не компилируется?

(Примечание: я не обязательно спрашиваю о решении проблемы, но объясню.)

Если мне нужно уточнить, не стесняйтесь спрашивать.

EDIT: если позвоните: copy(i, j); GNU GCC Compiler дает: ошибка: нет соответствующей функции для вызова функции «копировать (int &, int &)» примечание: кандидат: шаблон void copy (Buf &&, buf &) примечание: не удалось вывести / заменить аргумент шаблона: примечание: вывели конфликтующие типы для параметра 'Buf' ('int &' и 'int')

если звоните: copy<int&>(i, j); OK.

1 Ответ

0 голосов
/ 06 ноября 2018

а) Тип вычета для справка о пересылке :

template<class T>
void f(T&& val) {}

[a.1] при прохождении Lvalue T выводится как T&. Итак, у вас есть

void f(T& && ){} -after reference collapsing-> void f(T&){}

[a.2] при передаче R-значения T выводится как T. Итак, у вас есть

void f(T&& ) {}

b) Тип вычета для справки, кроме отправка справки :

template<class T>
void f(T& param){}

когда вы передаете Lvalue, T выводится как T. param имеет тип T&, но аргумент шаблона - T, а не T&.

Так код ниже компилируется

int i = 10;
copy(20,i);

потому что тип удержания для первого аргумента возвращает Buf==int, так как вы передали 20 Rvalue. И результат удержания для второго аргумента также возвращает Buf==int. Так в обоих случаи Buf одинаковы, код компилируется.

Код, который не компилируется:

int i=1;
int j=2;
copy(i,j);

Что такое выводимый тип для первого аргумента? Вы передаете L-значение, поэтому Buf равно int&. Второй вычет возвращает Buf==int. Эти два выведенных типа не совпадают, поэтому код не компилируется.

...