1*da0073e9SAndroid Build Coastguard Worker #ifndef C10_UTIL_OPTIONAL_H_
2*da0073e9SAndroid Build Coastguard Worker #define C10_UTIL_OPTIONAL_H_
3*da0073e9SAndroid Build Coastguard Worker
4*da0073e9SAndroid Build Coastguard Worker #include <optional>
5*da0073e9SAndroid Build Coastguard Worker #include <type_traits>
6*da0073e9SAndroid Build Coastguard Worker
7*da0073e9SAndroid Build Coastguard Worker // Macros.h is not needed, but it does namespace shenanigans that lots
8*da0073e9SAndroid Build Coastguard Worker // of downstream code seems to rely on. Feel free to remove it and fix
9*da0073e9SAndroid Build Coastguard Worker // up builds.
10*da0073e9SAndroid Build Coastguard Worker
11*da0073e9SAndroid Build Coastguard Worker namespace c10 {
12*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(misc-unused-using-decls)
13*da0073e9SAndroid Build Coastguard Worker using std::bad_optional_access;
14*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(misc-unused-using-decls)
15*da0073e9SAndroid Build Coastguard Worker using std::make_optional;
16*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(misc-unused-using-decls)
17*da0073e9SAndroid Build Coastguard Worker using std::nullopt;
18*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(misc-unused-using-decls)
19*da0073e9SAndroid Build Coastguard Worker using std::nullopt_t;
20*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(misc-unused-using-decls)
21*da0073e9SAndroid Build Coastguard Worker using std::optional;
22*da0073e9SAndroid Build Coastguard Worker
23*da0073e9SAndroid Build Coastguard Worker namespace detail_ {
24*da0073e9SAndroid Build Coastguard Worker // the call to convert<A>(b) has return type A and converts b to type A iff b
25*da0073e9SAndroid Build Coastguard Worker // decltype(b) is implicitly convertible to A
26*da0073e9SAndroid Build Coastguard Worker template <class U>
convert(U v)27*da0073e9SAndroid Build Coastguard Worker constexpr U convert(U v) {
28*da0073e9SAndroid Build Coastguard Worker return v;
29*da0073e9SAndroid Build Coastguard Worker }
30*da0073e9SAndroid Build Coastguard Worker } // namespace detail_
31*da0073e9SAndroid Build Coastguard Worker template <class T, class F>
value_or_else(const std::optional<T> & v,F && func)32*da0073e9SAndroid Build Coastguard Worker constexpr T value_or_else(const std::optional<T>& v, F&& func) {
33*da0073e9SAndroid Build Coastguard Worker static_assert(
34*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<typename std::invoke_result_t<F>, T>,
35*da0073e9SAndroid Build Coastguard Worker "func parameters must be a callable that returns a type convertible to the value stored in the optional");
36*da0073e9SAndroid Build Coastguard Worker return v.has_value() ? *v : detail_::convert<T>(std::forward<F>(func)());
37*da0073e9SAndroid Build Coastguard Worker }
38*da0073e9SAndroid Build Coastguard Worker
39*da0073e9SAndroid Build Coastguard Worker template <class T, class F>
value_or_else(std::optional<T> && v,F && func)40*da0073e9SAndroid Build Coastguard Worker constexpr T value_or_else(std::optional<T>&& v, F&& func) {
41*da0073e9SAndroid Build Coastguard Worker static_assert(
42*da0073e9SAndroid Build Coastguard Worker std::is_convertible_v<typename std::invoke_result_t<F>, T>,
43*da0073e9SAndroid Build Coastguard Worker "func parameters must be a callable that returns a type convertible to the value stored in the optional");
44*da0073e9SAndroid Build Coastguard Worker return v.has_value() ? constexpr_move(std::move(v).contained_val())
45*da0073e9SAndroid Build Coastguard Worker : detail_::convert<T>(std::forward<F>(func)());
46*da0073e9SAndroid Build Coastguard Worker }
47*da0073e9SAndroid Build Coastguard Worker } // namespace c10
48*da0073e9SAndroid Build Coastguard Worker #endif // C10_UTIL_OPTIONAL_H_
49