Возврат Необязательное значение с помощью оператора::
Мне часто нужно использовать необязательный тип для функций:
std::optional<int32_t> get(const std::string& field)
{
auto it = map.find(field);
if (it != map.end()) return it->second;
return {};
}
Есть ли способ вернуть необязательное значение в одной строке? например это:
std::optional<int32_t> get(const std::string& field)
{
auto it = map.find(field);
return it != map.end() ? it->second : {};
}
приводит к ошибке
error: expected primary-expression before '{' token
return it != map.end() ? it->second : {};
^
Ответы
Ответ 1
Вы можете явно перенести возврат некоторого значения в std::optional
и вернуться к constexpr
std::nullopt
для возврата no-value.
std::nullopt
:
std::nullopt
является константой типа std::nullopt_t
, которая используется для укажите необязательный тип с неинициализированным состоянием.
...
std::nullopt_t
:
std::nullopt_t
- это пустой тип класса, используемый для указания необязательного типа с неинициализированным состоянием. В частности, std::optional
имеет конструктор с nullopt_t
как один аргумент, который создает необязательный, который не содержит значения.
При таком подходе истинное предложение тернарного вызова оператора явно возвращает std::optional
с некоторым значением, поэтому компилятор может вывести параметр шаблона/завернутый тип (в этом примере: int32_t
) из типа от поставляемого завернутого значения, то есть вам не нужно явно указывать его.
Применяется к вашему примеру:
return it != map.end() ? std::optional(it->second) : std::nullopt;
// alternatively
return it != map.end() ? std::make_optional(it->second) : std::nullopt;
Ответ 2
return it != map.end() ? it->second : std::optional<int32_t>{};
должен сделать трюк.
Компилятор должен вывести тип результата тройного выражения из двух последних операндов, но он не может выводить std::optional<int32_t>
из int32_t
и {}
.
int32_t
и std::optional<int32_t>
, с другой стороны, имеют желаемый общий тип std::optional<int32_t>
.
Связанный забавный факт: вы можете избежать повторения типа с выводом типа автоматического возврата:
auto get(const std::string& field)
{
auto it = map.find(field);
return it != map.end() ? it->second : std::optional<int32_t>{};
}
В зависимости от предпочтения вы также можете вывести аргумент шаблона для std::optional
из it->second
с помощью decltype
, чтобы еще больше уменьшить повторение.