стрелка (->) в заголовке функции

128

Я наткнулся на следующий код:

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

Я не могу понять одного:

Где я мог узнать, что означает стрелка operator ( ->) в заголовке функции? Я предполагаю чисто логически, что ->оператор определяет тип, который autoбудет выведен, но я хочу понять это прямо. Я не могу найти никакой информации.

user1234567
источник
2
Это часть синтаксиса конечного возвращаемого типа. См. Stackoverflow.com/a/4113390/962089
Крис
2
Это не оператор, а часть синтаксиса.
Texasbruce,
1
В ответ на вопрос «где я могу прочитать?» Спецификация C ++ является наиболее авторитетной. Не имея средств или желания потратить $$, последний рабочий черновик часто оказывается достаточно близким и бесплатным. Эти спецификации носят технический характер, поэтому, не имея опыта чтения спецификаций ISO, попробуйте cplusplus.com или cppreference.com или другие подобные сайты, которые не являются авторитетными, но обычно очень точны. Примечание: конечный возвращаемый тип может быть опущен, начиная с C ++ 14.
Les,

Ответы:

205

В C ++ 11 есть два синтаксиса для объявления функции:

    декларации аргументов идентификатора возвращаемого типа ( ... )

и

    auto идентификатор ( аргумент-объявления ... ) -> return_type

Они эквивалентны. Теперь, когда они эквивалентны, почему вы вообще хотите использовать последнее? Что ж, C ++ 11 представил эту замечательную decltypeвещь, которая позволяет вам описывать тип выражения. Таким образом, вы можете захотеть получить тип возвращаемого значения из типов аргументов. Итак, вы пытаетесь:

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

и компилятор скажет вам, что он не знает, что aи bнаходится вdecltype аргументе. Это потому, что они объявляются только списком аргументов.

Вы можете легко обойти проблему, используя declvalи уже объявленные параметры шаблона. Подобно:

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

за исключением того, что теперь он становится действительно многословным. Таким образом, был предложен и реализован альтернативный синтаксис объявления, и теперь вы можете написать

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

и он менее подробный, и правила определения объема не нужно менять.


Обновление C ++ 14: C ++ 14 также позволяет

    auto идентификатор ( аргумент-объявления ... )

пока функция полностью определена перед использованием и все returnоператоры относятся к одному и тому же типу. ->Синтаксис остается полезным для общественных функций (объявленных в заголовке) , если вы хотите , чтобы скрыть тело в исходном файле. В некоторой степени очевидно, что это невозможно сделать с помощью шаблонов, но есть некоторые конкретные типы (обычно получаемые с помощью метапрограммирования шаблонов), которые трудно написать иначе.

Ян Худек
источник
2
очень хороший, аккуратный и информативный ответ @Jan Hudec. Пальцы вверх. Что-то изменилось, C++14поскольку я использую autoдля returnввода такой функции без необходимости в -> decltype(a + b)части. Является ли это избыточным сейчас или есть другие случаи, когда его все еще следует использовать? или это расширение для конкретного компилятора?
Шади
1
@Shadi, C ++ 14 включает N3638 , который позволяет вывести возвращаемый тип, объявленный как auto, без ->нотации, если функция полностью определена перед использованием и все returnоператоры выводятся к одному и тому же типу. ->Обозначения еще полезно , если вы хотите использовать вычет для публичной функции, скрывая тело в исходном файле.
Ян Худек
23

На простом английском языке он говорит, что возвращаемый тип является предполагаемым типом суммы aи b.

murrekatt
источник