У меня есть несколько функций, которые возвращают std::optional<T>
. Вот пример для вымышленного типа MyType
:
struct MyType {
// ...
}
std::optional<MyType> calculateOptional() {
// ... lengthy calculation
if (success) {
return MyType(/* etc */);
}
return std::nullopt;
}
Предположим, что эти функции выполняются дорого, и я хочу не вызывать их более одного раза.
При вызове их Я хочу немедленно протестировать необязательное, и если оно содержит значение, я хочу использовать его немедленно и никогда больше. Например, в Swift я могу использовать стандартное выражение if-let
:
if let result = calculateOptional() {
// Use result var
}
Я хотел бы повторить это поведение test-and-unwrap в C ++, сохраняя при этом код максимально чистым на точка использования. Например, очевидное простое решение (по крайней мере для меня) было бы:
if (auto result = calculateOptional()) {
MyType result_unwrapped = *result;
// Use result_unwrapped var
}
Но вы должны развернуть внутри if
или использовать *result
везде, что вам не нужно делать со Swift.
Мое единственное решение, которое действительно близко приближается к внешнему виду и ощущениям Swift:
template<typename T> bool optionalTestUnwrap(std::optional<T> opt, T& value) {
if (!opt.has_value()) { return false; }
value = *opt;
return true;
}
#define ifopt(var, opt) if (typename decltype((opt))::value_type (var); optionalTestUnwrap((opt), (var)))
ifopt (result, calculateOptional()) {
// Use result var
}
... но я также не большой поклонник использование макроса для замены нормального оператора if
.