Может ли ссылка на пересылку быть наложена псевдонимом шаблона?
Это продолжение моего предыдущего вопроса:
Может ли шаблон псевдонима идентификации быть ссылкой для пересылки?
Кажется, что следующий код работает как в 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);
}
Правильны ли компиляторы заменить шаблон псевдонима ссылкой для пересылки, и это может быть причудливым способом написания?
1 ответ
Это действительно соответствует стандарту. §14.5.7/2:
Когда идентификатор шаблона ссылается на специализацию шаблона псевдонима, он эквивалентен связанному типу, полученному путем подстановки его аргументов шаблона для параметров шаблона в идентификаторе типа шаблона псевдонима.
Теперь учтите, что при выводе аргумента шаблона проверяется только тип параметра (в терминах параметров шаблона) - §14.8.2.1/1:
Вывод аргумента шаблона выполняется путем сравнения каждого типа параметра шаблона функции (вызовите его
P
) с типом соответствующего аргумента вызова (вызвать егоA
), как описано ниже.
Согласно первой цитате, тип параметра, т.е. forwarding_reference<T>
, эквивалентно T&&
, следовательно P
является T&&
и не может быть никакой разницы в отношении вычета.
Такой же вывод был сделан комитетом в отчете о дефекте относительно этого точного сценария № 1700:
Поскольку типы параметров функции одинаковы, независимо от того, были ли они записаны напрямую или через шаблон псевдонимов, вычет должен обрабатываться одинаково в обоих случаях.