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:
auto const& Example(int const& i)
{
return i;
}
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ść:
template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args)
{
return fun(std::forward<Args>(args)...);
}
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>{}))
zamiast decltype(auto)
.
template<int i>
struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(Int<i>) -> decltype(auto)
{ return iter(Int<i-1>{}); }
int main() { decltype(iter(Int<10>{})) a; }
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]
1 auto
i decltype(auto)
typu specy fi ers wyznaczyć zastępczy typ, który zostanie zastąpiony później, albo poprzez odliczenie od inicjatora lub wyraźnej specy fi kacji z zwrotny typu wleczonego. Specyfikator auto
typu jest również używany do wskazania, że lambda to rodzajowa lambda.
2 Typ symbolu zastępczego może pojawić się z deklaratorem funkcji w sekwencji-specyfikatora-deklaracji, sekwencji-specyfikatora-typu, id-funkcji-konwersji lub typ-zwracanego-końcowego- w dowolnym kontekście, w którym taki deklarator jest prawidłowy . Jeśli deklarator funkcji zawiera końcowy-zwracany-typ (8.3.5), określa on zadeklarowany typ zwracania funkcji. Jeśli zadeklarowany zwracany typ funkcji zawiera typ zastępczy, zwracany typ funkcji jest wywnioskowany z instrukcji return w treści funkcji, jeśli takie istnieją.
Wersja robocza zawiera również następujący przykład inicjalizacji zmiennej:
int i;
int&& f();
auto x3a = i; // decltype(x3a) is int
decltype(auto) x3d = i; // decltype(x3d) is int
auto x4a = (i); // decltype(x4a) is int
decltype(auto) x4d = (i); // decltype(x4d) is int&
auto x5a = f(); // decltype(x5a) is int
decltype(auto) x5d = f(); // decltype(x5d) is int&&
auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i; // decltype(x7a) is int*
decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)