opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
value_or_sentinel.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <format>
5#include <optional>
6#include <ostream>
7#include <type_traits>
8#include <utility>
9
10namespace osc
11{
15 template<typename T, T Sentinel>
16 class ValueOrSentinel final {
17 public:
18 using value_type = T;
19
20 static constexpr T sentinel() { return Sentinel; }
21
22 constexpr ValueOrSentinel() = default;
23
24 template<class U = std::remove_cv_t<T>>
25 requires std::constructible_from<T, U&&>
26 constexpr ValueOrSentinel(U&& value) : value_(std::forward<U>(value)) {}
27
28 friend constexpr bool operator==(ValueOrSentinel, ValueOrSentinel) = default;
29
30 template<typename U>
31 friend constexpr bool operator==(const ValueOrSentinel& lhs, const U& rhs) { return *lhs == rhs; }
32
33 template<typename U>
34 friend constexpr bool operator==(const U& lhs, const ValueOrSentinel& rhs) { return lhs == *rhs; }
35
36 explicit constexpr operator bool () const { return value_ != Sentinel; }
37
38 constexpr const T& operator*() const& noexcept { return value_; }
39 constexpr T& operator*() & noexcept { return value_; }
40 constexpr const T&& operator*() const&& noexcept { return std::move(value_); }
41 constexpr T&& operator*() && noexcept { return std::move(value_); }
42 constexpr const T& value() const& { return *this ? value_ : throw std::bad_optional_access{}; }
43 constexpr T& value() & { return *this ? value_ : throw std::bad_optional_access{}; }
44 constexpr const T&& value() const&& { return *this ? std::move(value_) : throw std::bad_optional_access{}; }
45 constexpr T&& value() && { return *this ? std::move(value_) : throw std::bad_optional_access{}; }
46
47 private:
48 T value_ = Sentinel;
49 };
50
51 template<typename T, T Sentinel>
52 std::ostream& operator<<(std::ostream& lhs, const ValueOrSentinel<T, Sentinel>& rhs)
53 {
54 return lhs << std::format("{}", rhs);
55 }
56}
57
58template<typename T, T Sentinel>
59struct std::formatter<osc::ValueOrSentinel<T, Sentinel>> {
60 template<class ParseCtx>
61 constexpr auto parse(ParseCtx& ctx) { return inner_.parse(ctx); }
62
63 template<class FmtCtx>
64 auto format(const osc::ValueOrSentinel<T, Sentinel>& v, FmtCtx& ctx) const
65 {
66 auto it = std::ranges::copy(std::string_view{"ValueOrSentinel("}, ctx.out()).out;
67 it = inner_.format(*v, ctx);
68 *it++ = ')';
69 return it;
70 }
71private:
72 std::formatter<T> inner_;
73};
Definition value_or_sentinel.h:16
T value_type
Definition value_or_sentinel.h:18
constexpr const T & value() const &
Definition value_or_sentinel.h:42
constexpr T && operator*() &&noexcept
Definition value_or_sentinel.h:41
static constexpr T sentinel()
Definition value_or_sentinel.h:20
constexpr T & value() &
Definition value_or_sentinel.h:43
friend constexpr bool operator==(ValueOrSentinel, ValueOrSentinel)=default
constexpr const T && value() const &&
Definition value_or_sentinel.h:44
constexpr const T && operator*() const &&noexcept
Definition value_or_sentinel.h:40
friend constexpr bool operator==(const ValueOrSentinel &lhs, const U &rhs)
Definition value_or_sentinel.h:31
constexpr T & operator*() &noexcept
Definition value_or_sentinel.h:39
constexpr const T & operator*() const &noexcept
Definition value_or_sentinel.h:38
constexpr ValueOrSentinel()=default
constexpr T && value() &&
Definition value_or_sentinel.h:45
friend constexpr bool operator==(const U &lhs, const ValueOrSentinel &rhs)
Definition value_or_sentinel.h:34
constexpr ValueOrSentinel(U &&value)
Definition value_or_sentinel.h:26
Definition custom_decoration_generator.h:5
std::ostream & operator<<(std::ostream &, const Object &)
constexpr auto parse(ParseCtx &ctx)
Definition value_or_sentinel.h:61
auto format(const osc::ValueOrSentinel< T, Sentinel > &v, FmtCtx &ctx) const
Definition value_or_sentinel.h:64