decltype na variável do tipo de referência com chaves
Considere o seguinte código :
#include <type_traits>
int main() {
const int& p = 42;
auto v1 = decltype(p){};
static_assert(std::is_same_v<decltype(v1), int>);
decltype(p) v2{};
static_assert(std::is_same_v<decltype(v2), const int&>);
// auto v3 = X(const int&)X {};
}
O tipo de v1
é deduzido como int
. Ao mesmo tempo, o tipo de v2
é esperado como const int&
. Acho que o primeiro passo para v1
poderia ser tratado como adicionar mais um alias de tipo using T = decltype(p);
e então auto v4 = T{};
. Como esta expressão ( decltype(p){}
ou T{}
) é tratada pelo compilador? Eu sei que essa {}
parte é para instanciação, mas como o tipo resultante de v1
não é um tipo de referência?
Ainda outra pergunta: há uma maneira de declarar v3
variável do mesmo tipo que v1
usar tipo explicitamente anotado const int&
(em vez de decltype(p)
)?
Quaisquer links para o padrão serão apreciados.
Respostas
(Para o (s) downvoter (es): se você votou contra porque acha que citar Scott Meyers não é equivalente a citar o padrão, tudo bem ...)
Como você pode ler em Effective Modern C ++ (ampliado com a parte da errata que você pode alcançar pesquisando Case 2:
nesse link, e isso apenas torna a leitura a seguir mais simples, mas não é essencial para a questão):
Se não
ParamType
for uma referência [...] seexpr
o tipo for uma referência, ignore a parte da referência. Seexpr
forconst
, ingore isso também. Se forvolatile
, ignore também.
onde param
está o especificador de declaração, que no seu caso é justo auto
, ou seja, uma não referência.
Em outras palavras, você está criando v1
via simples auto
(não auto&
), ou seja, por cópia, então não importa se você está inicializando com uma entidade que é referência ou não, ou mesmo com const
ou não ( volatile
ou não, fwiw), porque você está copiando.
Pense no caso mais simples,
int i = 3;
int& p = i;
auto v1 = p;
no que diz v1
respeito a isso, realmente não é importante se ele é inicializado com um ( i
) ou outro ( p
) nome pelo qual a mesma entidade é conhecida, porque ela obterá uma cópia de qualquer valor que essa entidade tenha.
auto
a dedução de tipo funciona da mesma forma que a dedução de tipo de modelo (exceto por uma diferença em como eles lidam com o inicializador com chaves, que não é relevante neste caso), e para ambos você pode consultar o Effective Modern C ++ de Scott Meyers .