operator strzałki (->) w nagłówku funkcji

128

Natknąłem się na następujący kod:

template <typename T, typename T1> auto compose(T a, T1 b) -> decltype(a + b) {
   return a+b;
}

Nie mogę zrozumieć jednej rzeczy:

Gdzie mogę się dowiedzieć, co oznacza operator strzałki ( ->) w nagłówku funkcji? Myślę, że czysto logicznie, że ->operator określa typ, do którego autozostanie wydedukowany, ale chcę to wyjaśnić. Nie mogę znaleźć żadnych informacji.

user1234567
źródło
2
Jest częścią składni końcowego zwracanego typu. Zobacz stackoverflow.com/a/4113390/962089
chris
2
Nie jest operatorem, ale częścią składni.
texasbruce
1
W odpowiedzi na pytanie „gdzie mogę czytać?”, Specyfikacja C ++ jest najbardziej miarodajna. Brak funduszy lub chęć wydania $$, ostatni roboczy projekt jest często wystarczająco blisko i nie kosztuje. Specyfikacje te są wysoce techniczne, więc nie znając czytania specyfikacji ISO, wypróbuj cplusplus.com lub cppreference.com lub inne podobne witryny, które nie są autorytatywne, ale zwykle są bardzo dokładne. Uwaga: końcowy zwracany typ można pominąć, zaczynając od C ++ 14.
Les

Odpowiedzi:

205

W C ++ 11 istnieją dwie składnie deklaracji funkcji:

    deklaracje typu zwracanego identyfikatora ( argumentów ... )

i

    auto identyfikator ( deklaracje-argumentów ... ) -> typ_powrotu

Są równoważne. Skoro są równoważne, dlaczego kiedykolwiek chcesz używać tych drugich? Cóż, C ++ 11 wprowadził tę fajną decltyperzecz, która pozwala opisać typ wyrażenia. Więc możesz chcieć wyprowadzić typ zwracany z typów argumentów. Więc spróbuj:

template <typename T1, typename T2>
decltype(a + b) compose(T1 a, T2 b);

a kompilator powie ci, że nie wie, co ai bsą w decltypeargumencie. Dzieje się tak, ponieważ są one deklarowane tylko przez listę argumentów.

Możesz łatwo obejść ten problem, używając declvali parametrów szablonu, które są już zadeklarowane. Lubić:

template <typename T1, typename T2>
decltype(std::declval<T1>() + std::declval<T2>())
compose(T1 a, T2 b);

z wyjątkiem tego, że robi się teraz naprawdę rozwlekły. Tak więc alternatywna składnia deklaracji została zaproponowana i zaimplementowana, a teraz możesz pisać

template <typename T1, typename T2>
auto compose(T1 a, T2 b) -> decltype(a + b);

i jest mniej szczegółowy, a zasady określania zakresu nie musiały się zmieniać.


Aktualizacja C ++ 14: C ++ 14 również pozwala tylko

    auto identyfikator ( deklaracji argumentów ... )

o ile funkcja jest w pełni zdefiniowana przed użyciem, a wszystkie returninstrukcje wywodzą się z tego samego typu. ->Składnia pozostaje użyteczna dla funkcji publicznych (zadeklarowane w nagłówku), jeśli chcesz, aby ukryć ciało w pliku źródłowym. W pewnym sensie nie można tego zrobić za pomocą szablonów, ale istnieją pewne konkretne typy (zwykle uzyskiwane za pomocą metaprogramowania szablonów), które są trudne do napisania w inny sposób.

Jan Hudec
źródło
2
bardzo dobra, zgrabna i pouczająca odpowiedź @Jan Hudec. Kciuki w górę. Czy coś się zmieniło, C++14gdy używam autodo returnpisania w takiej funkcji bez potrzeby -> decltype(a + b)części. Czy jest już zbędny, czy ma inne przypadki, w których nadal powinien być używany? czy jest to rozszerzenie specyficzne dla kompilatora?
Shadi
1
@Shadi, C ++ 14 zawiera N3638 , który pozwala na odliczenie zwracanego typu zadeklarowanego jako auto, bez ->notacji, o ile funkcja jest w pełni zdefiniowana przed użyciem, a wszystkie returninstrukcje są dedukowane do tego samego typu. ->Notacja jest nadal przydatna, jeśli chcesz korzystać z odliczenia dla funkcji publicznej, ukrywając ciało w pliku źródłowym.
Jan Hudec
23

W prostym języku angielskim mówi, że typ zwracany jest wywnioskowanym typem sumy ai b.

murrekatt
źródło