W języku c ++ 14 wprowadzono decltype(auto)
idiom.
Zwykle służy do zezwalania auto
deklaracjom na używanie decltype
reguł dla danego wyrażenia .
Szukając przykładów „dobrego” użycia idiomu, przychodzą mi do głowy tylko następujące rzeczy (autorstwa Scotta Meyersa ), a mianowicie dedukcja typu zwracanego funkcji :
template<typename ContainerType, typename IndexType> // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
authenticateUser();
return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
Czy są jakieś inne przykłady, w których ta nowa funkcja języka jest przydatna?
decltype(auto)
czegoś podobnegotemplate<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }
, ale potem zdałem sobie sprawę, że muszę użyć,return (p.first);
co zadziwiająco działa (ale IIRC jest nawet przeznaczone).decltype(auto)
może to spowodować skopiowanie / przeniesienie czegoś do zadeklarowanego obiektu, wbrew oczekiwaniom.Odpowiedzi:
Przekazywanie typu zwrotnego w kodzie ogólnym
W przypadku kodu nieogólnego, takiego jak podany w początkowym przykładzie, możesz ręcznie wybrać, aby uzyskać odwołanie jako typ zwracany:
ale w kodzie ogólnym chcesz mieć możliwość perfekcyjnego przekazywania zwracanego typu bez wiedzy, czy masz do czynienia z odwołaniem, czy z wartością.
decltype(auto)
daje ci tę możliwość:Opóźnianie potrącenia typu zwrotu w szablonach cyklicznych
W tym pytaniu i odpowiedzi kilka dni temu napotkano nieskończoną rekursję podczas tworzenia wystąpienia szablonu, gdy typ zwracanego szablonu został określony jako
decltype(iter(Int<i-1>{}))
zamiastdecltype(auto)
.decltype(auto)
jest tutaj używany do opóźnienia odliczenia typu zwracanego po ustąpieniu kurzu instancji szablonu.Inne zastosowania
Można również używać
decltype(auto)
w innych kontekstach, np. W projekcie normy N3936 podano również7.1.6.4 specyfikacja automatyczna [dcl.spec.auto]
Wersja robocza zawiera również następujący przykład inicjalizacji zmiennej:
źródło
(i)
vsi
nową rzeczą w C ++ 14?decltype(expr)
idecltype((expr))
są już inne w C ++ 11, to uogólnia to zachowanie.auto
wykonałby zadanie równie dobrze, ponieważ wynik i tak jest zwracany przez wartość ... A może przegapiłem coś?Cytując rzeczy z tego miejsca :
decltype(auto)
jest przede wszystkim przydatny do określania zwracanego typu funkcji przekazujących i podobnych opakowań , w przypadku których chcesz, aby typ dokładnie „śledził” wywoływane wyrażenie.Na przykład, biorąc pod uwagę poniższe funkcje:
Jednak
decltype(auto)
nie ma być szeroko używaną funkcją poza tym.W szczególności, chociaż może być używany do deklarowania zmiennych lokalnych , zrobienie tego prawdopodobnie jest tylko anty-wzorcem, ponieważ odwołanie do zmiennej lokalnej nie powinno zależeć od wyrażenia inicjującego.
Ponadto jest wrażliwy na sposób pisania instrukcji return.
Na przykład dwie poniższe funkcje mają różne typy zwracanych wartości:
string
, drugi zwracastring&
, czyli odwołanie do zmiennej lokalnejstr
.Z propozycji można zobaczyć więcej zamierzonych zastosowań.
źródło
auto
do zwrotu?auto
), ale OP poprosił o użyciedecltype(auto)
.auto lookup_a_string() { ... }
? Czy zawsze jest to typ bez odniesienia? Czy w związku z tymauto lookup_a_string() ->decltype(auto) { ... }
konieczne jest wymuszenie zezwolenia na (w niektórych przypadkach) zwrotu referencji?auto
jest zdefiniowane w ramach szablonu pass by value, więc tak, nie może być odniesieniem. Proszę czekać,auto
może to być oczywiście wszystko, łącznie z odniesieniem.std::vector
. Powiedz, że masztemplate<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }
. NastępnieS<bool>::operator[]
zwróci wiszące referencje ze względu na specjalizacjęstd::vector<bool>
. Zmiana typu powrotu w celudecltype(auto)
obejścia tego problemu.