|
| constexpr | sentinel_optional (std::nullopt_t) noexcept |
| template<class... TYPES, std::enable_if_t< std::is_constructible_v< T, TYPES... >, int > = 0> |
| constexpr | sentinel_optional (std::in_place_t, TYPES &&... args) noexcept(std::is_nothrow_constructible_v< T, TYPES... >) |
| template<class U = T, std::enable_if_t< !std::is_same_v< remove_cvref_t< U >, sentinel_optional > &&!std::is_same_v< remove_cvref_t< U >, std::in_place_t > &&!std::is_same_v< std::remove_cv_t< U >, bool > &&std::is_constructible_v< T, U >, int > = 0> |
| constexpr | sentinel_optional (U &&right) noexcept(std::is_nothrow_constructible_v< T, U >) |
| template<class U, std::enable_if_t< std::is_constructible_v< T, const U & >, int > = 0> |
| constexpr | sentinel_optional (const sentinel_optional< U > &right) noexcept(std::is_nothrow_constructible_v< T, const U & >) |
| template<class U, std::enable_if_t< std::is_constructible_v< T, U >, int > = 0> |
| constexpr | sentinel_optional (sentinel_optional< U > &&right) noexcept(std::is_nothrow_constructible_v< T, U >) |
| constexpr sentinel_optional & | operator= (std::nullopt_t) noexcept |
| template<class U = T, std::enable_if_t< !std::is_same_v< sentinel_optional, remove_cvref_t< U > > &&std::is_constructible_v< T, U > &&std::is_assignable_v< T &, U >, int > = 0> |
| constexpr sentinel_optional & | operator= (U &&right) noexcept(std::is_nothrow_assignable_v< T &, U > &&std::is_nothrow_constructible_v< T, U >) |
| template<class U, std::enable_if_t< !(std::is_same_v< T, U >||std::is_assignable_v< T &, sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > >||std::is_assignable_v< T &, sentinel_optional< U > >) &&std::is_constructible_v< T, const U & > &&std::is_assignable_v< T &, const U & >, int > = 0> |
| constexpr sentinel_optional & | operator= (const sentinel_optional< U > &right) noexcept(std::is_nothrow_assignable_v< T &, const U & > &&std::is_nothrow_constructible_v< T, const U & >) |
| template<class U, std::enable_if_t< !(std::is_same_v< T, U >||std::is_assignable_v< T &, sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > >||std::is_assignable_v< T &, sentinel_optional< U > >) &&std::is_constructible_v< T, U > &&std::is_assignable_v< T &, U >, int > = 0> |
| constexpr sentinel_optional & | operator= (sentinel_optional< U > &&right) noexcept(std::is_nothrow_assignable_v< T &, U > &&std::is_nothrow_constructible_v< T, U >) |
| template<class... TYPES> |
| constexpr T & | emplace (TYPES &&... args) noexcept(std::is_nothrow_constructible_v< T, TYPES... >) |
| constexpr void | assert_value () const |
| constexpr const T * | operator-> () const |
| constexpr T * | operator-> () |
| constexpr T & | operator* () & |
| constexpr const T & | operator* () const & |
| constexpr T && | operator* () && |
| constexpr const T && | operator* () const && |
| constexpr bool | has_value () const noexcept |
| constexpr | operator bool () const noexcept |
| constexpr const T & | value () const & |
| constexpr T & | value () & |
| constexpr T && | value () && |
| constexpr const T && | value () const && |
| constexpr const T & | raw_value () const & |
| | Returns the value without asserting has_value().
|
| constexpr T & | raw_value () & |
| | Returns the value without asserting has_value().
|
| constexpr T && | raw_value () && |
| | Returns the value without asserting has_value().
|
| constexpr const T && | raw_value () const && |
| | Returns the value without asserting has_value().
|
| constexpr void | reset () noexcept |
|
| constexpr bool | operator== (const sentinel_optional &lhs, const sentinel_optional &rhs) |
| constexpr bool | operator!= (const sentinel_optional &lhs, const sentinel_optional &rhs) |
| constexpr bool | operator< (const sentinel_optional &lhs, const sentinel_optional &rhs) |
| constexpr bool | operator<= (const sentinel_optional &lhs, const sentinel_optional &rhs) |
| constexpr bool | operator> (const sentinel_optional &lhs, const sentinel_optional &rhs) |
| constexpr bool | operator>= (const sentinel_optional &lhs, const sentinel_optional &rhs) |
| constexpr auto | operator<=> (const sentinel_optional &lhs, const sentinel_optional &rhs) |
| constexpr bool | operator== (const sentinel_optional &opt, std::nullopt_t) |
| constexpr auto | operator<=> (const sentinel_optional &opt, std::nullopt_t) |
template<typename T, auto SENTINEL = T{}, typename EQ = detail::better_equal_to>
struct ghassanpl::sentinel_optional< T, SENTINEL, EQ >
An equivalent to std::optional<T> except that instead of keeping an additional bool to indicate value presence, it uses one of the potential values of T as a "sentinel" value to indicate nullopt.
This makes the value the same size/alignment as T while still keeping the optional API. Mostly useful for enums or special types, somewhat useful for floating-points, sometimes useful for pointers.
- Note
- This TECHNICALLY could work with C++17, but its only practically useful with C++20 since SENTINEL can be of more types, especially floats.
- Template Parameters
-
| T | the value you want to hold |
| SENTINEL | a value that will represent the nullopt; needs to be assignable to T, and comparable with T using the EQ functor type |
| EQ | a functor type whose operator() will tell us if value == SENTINEL; exists because some types, like floats, cannot be straight-compared with NAN as a sentinel value |
Definition at line 55 of file soptional.h.
template<typename T, auto SENTINEL = T{}, typename EQ = detail::better_equal_to>
template<class U = T, std::enable_if_t< !std::is_same_v< remove_cvref_t< U >, sentinel_optional > &&!std::is_same_v< remove_cvref_t< U >, std::in_place_t > &&!std::is_same_v< std::remove_cv_t< U >, bool > &&std::is_constructible_v< T, U >, int > = 0>
template<typename T, auto SENTINEL = T{}, typename EQ = detail::better_equal_to>
template<class U, std::enable_if_t< !(std::is_same_v< T, U >||std::is_assignable_v< T &, sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > >||std::is_assignable_v< T &, sentinel_optional< U > >) &&std::is_constructible_v< T, const U & > &&std::is_assignable_v< T &, const U & >, int > = 0>
template<typename T, auto SENTINEL = T{}, typename EQ = detail::better_equal_to>
template<class U, std::enable_if_t< !(std::is_same_v< T, U >||std::is_assignable_v< T &, sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > & >||std::is_assignable_v< T &, const sentinel_optional< U > >||std::is_assignable_v< T &, sentinel_optional< U > >) &&std::is_constructible_v< T, U > &&std::is_assignable_v< T &, U >, int > = 0>