Подтвердить что ты не робот

Возврат Необязательное значение с помощью оператора::

Мне часто нужно использовать необязательный тип для функций:

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 : {};
                                      ^
4b9b3361

Ответ 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, чтобы еще больше уменьшить повторение.