decltype na zmiennej typu referencyjnego z nawiasami klamrowymi
Rozważ następujący kod :
#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 {};
}
Typ v1
jest wywnioskowany jako int
. Jednocześnie v2
oczekuje się, że typ const int&
. Myślę, że pierwszy krok v1
można potraktować jako dodanie jeszcze jednego aliasu typu, using T = decltype(p);
a następnie auto v4 = T{};
. Jak to wyrażenie ( decltype(p){}
lub T{}
) jest traktowane przez kompilator? Wiem, że ta {}
część jest przeznaczona do tworzenia instancji, ale w jaki sposób wynikowy typ v1
nie jest typem referencyjnym?
Jeszcze inne pytanie: czy istnieje sposób na zadeklarowanie v3
zmiennej tego samego typu, co v1
przy użyciu jawnie wskazanego typu const int&
(zamiast decltype(p)
)?
Wszelkie linki do standardu będą mile widziane.
Odpowiedzi
(Do przeciwników: jeśli zgodzisz się, ponieważ uważasz, że cytowanie Scotta Meyersa nie jest równoznaczne z cytowaniem normy, no cóż ...)
Jak możesz przeczytać w Effective Modern C ++ (wzbogaconym o część erraty , do której można dotrzeć, wyszukując Case 2:
ten link, a to tylko upraszcza czytanie, ale nie jest to niezbędne do pytania):
Jeśli nie
ParamType
jest odniesieniem [...] jeśliexpr
typ jest odniesieniem, zignoruj część odniesienia. Jeśli [...]expr
jestconst
, to też zrób to. Jeśli takvolatile
, zignoruj to.
gdzie param
jest specyfikatorem deklaracji, co w twoim przypadku jest po prostu auto
, tj. bez odniesienia.
Innymi słowy, tworzysz v1
przez zwykły auto
(nie auto&
), tj. Przez kopiowanie, więc nie ma znaczenia, czy inicjujesz go z bytem, który jest odniesieniem, czy nie, czy nawet z const
lub nie ( volatile
lub nie, fwiw), ponieważ to kopiujesz.
Pomyśl o prostszym przypadku,
int i = 3;
int& p = i;
auto v1 = p;
jeśli chodzi o v1
to, to naprawdę nie jest ważne, czy jest inicjowane jedną ( i
), czy drugą ( p
) nazwą, pod którą znana jest ta sama jednostka, ponieważ otrzyma kopię dowolnej wartości, jaką ma ta jednostka.
auto
dedukcja typów działa tak samo jak dedukcja typów szablonów (z wyjątkiem różnicy w sposobie, w jaki radzą sobie z inicjalizatorem ze wzmocnieniem, co nie jest istotne w tym przypadku) i dla obu z nich możesz odwołać się do Efektywnego nowoczesnego C ++ Scotta Meyersa .