8.8 – Вывод типа для функций
Рассмотрим следующий код:
int add(int x, int y)
{
return x + y;
}
Когда эта функция скомпилируется, компилятор определит, что x + y
вычисляется как int
, а затем убедится, что тип возвращаемого значения соответствует объявленному типу возвращаемого значения функции (или что тип возвращаемого значения может быть преобразован в объявленный тип возвращаемого значения).
Поскольку компилятор уже должен вывести тип возвращаемого значения из инструкции return
, в C++ 14 ключевое слово auto
было расширено, чтобы иметь возможность выводить тип возвращаемого значения функции из инструкций возврата в теле функции. Это работает за счет использования ключевого слова auto
вместо типа возвращаемого значения функции.
Например:
auto add(int x, int y)
{
return x + y;
}
Поскольку x + y
вычисляется как int
, компилятор определит, что эта функция должна иметь тип возвращаемого значения int
.
При использовании возвращаемого типа auto
все инструкции return
должны возвращать один и тот же тип, в противном случае возникнет ошибка. Например:
auto someFcn(bool b)
{
if (b)
return 5; // возвращаемый тип int
else
return 6.7; // возвращаемый тип double
}
В приведенной выше функции два инструкции return
возвращают значения разных типов, поэтому компилятор выдаст ошибку. Если по какой-то причине такой случай необходим, либо используйте static_cast
для некоторых или всех возвращаемых значений, чтобы они были одного типа, либо явно укажите для вашей функции тип возвращаемого значения.
В отличие от вывода типа для объектов, не существует единого мнения о лучших практиках использования вывода типа, возвращаемого функцией. При использовании вывода типа с объектами инициализатор всегда присутствует как часть той же инструкции, поэтому обычно не слишком трудно определить, какой тип будет выводиться. С функциями дело обстоит иначе – при просмотре прототипа функции нет контекста, который помог бы указать, какой тип она возвращает. Хорошая IDE для программирования должна четко указывать, какой выведен тип для функции, но при отсутствии этого функционала пользователю фактически придется копаться в самом теле функции, чтобы определить, какой тип она возвращает. Вероятность совершения ошибки здесь повышается.
Лучшая практика
Для обычных функций отдавайте предпочтение явным типам возврата, вместо автоматического вывода типа возвращаемого значения.
Синтаксис, завершающийся возвращаемым типом
Ключевое слово auto
также может использоваться для объявления функций с использованием синтаксиса, завершающегося возвращаемым значением (trailing return syntax), где тип возвращаемого значения указывается после остальной части прототипа функции.
Рассмотрим следующую функцию:
int add(int x, int y)
{
return (x + y);
}
Используя auto
, его можно было бы записать как:
auto add(int x, int y) -> int
{
return (x + y);
}
В этом случае auto
не выполняет вывод типа – это просто часть синтаксиса, использующего завершение типом возвращаемого значения.
Зачем вам это нужно?
Приятно, когда все имена функций выстраиваются в одну линию:
auto add(int x, int y) -> int;
auto divide(double x, double y) -> double;
auto printSomething() -> void;
auto generateSubstring(const std::string &s, int start, int len) -> std::string;
Синтаксис, завершающийся возвращаемым типом, также требуется для некоторых расширенных функций C++, таких как лямбда-выражения (которые мы рассмотрим в уроке «11.13 – Введение в лямбды (анонимные функции)»).
На данный момент мы рекомендуем продолжать использовать традиционный синтаксис возврата функции, за исключением ситуаций, требующих синтаксиса, завершающегося возвращаемым типом.
Вывод типа не может использоваться для типов параметров функции
Многие начинающие программисты пробуют писать что-то вроде этого:
#include <iostream>
void addAndPrint(auto x, auto y)
{
std::cout << x + y;
}
int main()
{
addAndPrint(2, 3); // случай 1: вызвать addAndPrint с параметрами типа int
addAndPrint(4.5, 6.7); // случай 2: вызов addAndPrint с параметрами типа double
}
К сожалению, вывод типа не работает для параметров функции, и до C++20 показанная выше программа не компилируется (вы получите сообщение об ошибке, что параметры функции не могут иметь тип auto
).
В C++20 ключевое слово auto
было расширено, чтобы указанная выше программа компилировалась и работала правильно, однако в этом случае auto
не вызывает вывод типа. Скорее, оно запускает другую функцию, называемую шаблонами функций, которая была разработана для обработки таких случаев.
Связанный контент
Мы рассмотрим шаблоны функций в уроке «8.13 – Шаблоны функций» и обсудим использование auto
в контексте шаблонов функций в уроке «8.15 – Шаблоны функций с несколькими шаблонными типами».