Ссылка на l-значение удержания шаблона функции и универсальная ссылка
Допустим, у меня есть функция 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-значение тоже; & + & -> &
,
Итак, вопрос: почему этот код не компилируется?
(Примечание: я не обязательно прошу решение проблемы, но объяснение.)
Если мне нужно уточнить, не стесняйтесь спрашивать.
РЕДАКТИРОВАТЬ: если позвоните: copy(i, j);
Компилятор GNU GCC выдает: error: нет соответствующей функции для вызова функции "copy(int&, int&)" note:андидат: шаблон void copy(Buf&&, buf&)
note: сбой вывода / замены аргумента шаблона: note: выведены конфликтующие типы для параметра 'Buf' ('int&'и'int')
если позвоните: copy<int&>(i, j);
ХОРОШО.
1 ответ
А) Тип вычета для пересылки ссылки:
template<class T>
void f(T&& val) {}
[a.1] когда вы передаете Lvalue T
выводится T&
, Так что у тебя есть
void f(T& && ){} -after reference collapsing-> void f(T&){}
[a.2] при прохождении Rvalue T
выводится T
, Так что у тебя есть
void f(T&& ) {}
б) Тип вычета для справки, кроме пересылки справки:
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
, Эти два выведенных типа не совпадают, поэтому код не компилируется.