Это продолжение моего предыдущего вопроса:
Может ли шаблон псевдонима идентификации быть ссылкой для пересылки?
Кажется, что следующий код работает в обоих Clang 3.7.0 (демонстрация) и GCC 6.0.0 (демонстрация):
template <class T>
using forwarding_reference = T&&;
template <class T>
void foo(forwarding_reference<T>) {}
int main()
{
int i{};
foo(i);
foo(1);
}
Правильны ли компиляторы заменить шаблон псевдонима ссылкой для пересылки, и это может быть причудливым способом написания?
Это действительно соответствует стандарту. §14.5.7 / 2:
Когда Шаблон-идентификатор относится к специализации шаблона псевдонима,
это эквивалентно ассоциированному типу, полученному путем замены
его Шаблон-аргументы для Шаблон-параметры в тип-идентификатор из
шаблон псевдонима.
Теперь учтите, что при выводе аргумента шаблона проверяется только тип параметра (в терминах параметров шаблона) — §14.8.2.1 / 1:
Вывод аргумента шаблона производится путем сравнения каждого функция
тип параметра шаблона (назовите егоP
) с типом
соответствующий аргумент вызова (назовите егоA
), как описано ниже.
Согласно первой цитате, тип параметра, т.е. forwarding_reference<T>
, эквивалентно T&&
, следовательно P
является T&&
и не может быть никакой разницы в отношении вычета.
Такой же вывод был сделан комитетом в отчете о дефектах относительно этого точного сценария, # 1700:
Поскольку типы параметров функции одинаковы, независимо от
независимо от того, написана ли она напрямую или через шаблон псевдонима,
обрабатываться одинаково в обоих случаях.