"arg" é uma referência universal/de encaminhamento ou uma referência de rvalue?
template<auto&& arg>
struct test {};
"arg" é uma referência universal/de encaminhamento ou uma referência de rvalue?
template<auto&& arg>
struct test {};
É uma referência de encaminhamento (também conhecida como universal).
É fácil verificar:
Isso compila apesar de
x
ser um lvalue.Conforme observado por @user12002570, o padrão aparentemente tem uma definição muito restrita de uma "referência de encaminhamento" que se aplica apenas a parâmetros de função, o que significa que tecnicamente não é uma ( a resposta de @Brian Bi discute isso em mais detalhes). Mas eu diria que a escolha das palavras é discretamente defeituosa, esta não é a definição que as pessoas geralmente usam.
Geralmente as pessoas dizem "uma referência de encaminhamento" para indicar que uma referência aparentemente rvalue pode se tornar uma referência lvalue se receber um lvalue, e a resposta neste caso é sim.
As referências de encaminhamento existem apenas para fins de [temp.deduct.call] .
Em
template <auto&& arg> struct test {};
, a referênciaarg
não é uma referência de encaminhamento. No entanto, quando um argumento de modelo é fornecido paraarg
, [temp.arg.nontype]/1 nos diz para inventar uma declaraçãoe o tipo de
arg
é o tipo dex
. Para encontrar o tipo dex
, temos que usar [dcl.type.auto.deduct]/3 , que então adia para [temp.deduct.call] com um parâmetro de função inventado typeU&&
. Aqui,P
isU&&
e é uma referência de encaminhamento. O parâmetro de templateU
não representa um parâmetro de template de um template de classe; em vez disso,U
foi obtido por "[substituindo] [...]auto
[...] com um novo parâmetro de template de tipo inventado", seguindo a redação em [dcl.type.auto.deduct]/3.Conforme declarado, não
arg
é uma referência de encaminhamento conforme temp.deduct.call :Observe a ênfase em negrito, o que torna esta referência não universal/de encaminhamento.
Note que a documentação do cppreference sobre encaminhamento de referência contradiz o padrão c++ aqui. Em particular, a página cppreference diz: