12 #ifndef DOCWIRE_CHECKED_H
13 #define DOCWIRE_CHECKED_H
15 #include "safety_policy.h"
18 #include <type_traits>
37 template <
typename Dereferenceable, safety_policy safety_level = default_safety_level>
53 checked(Dereferenceable&&
value) noexcept(std::is_nothrow_move_constructible_v<Dereferenceable>) : m_value(std::move(
value)) {}
58 template <
typename... Args,
59 typename = std::enable_if_t<
60 std::is_constructible_v<Dereferenceable, Args...> &&
61 (
sizeof...(Args) > 1 ||
62 (
sizeof...(Args) == 1 &&
63 ((!std::is_same_v<std::decay_t<Args>,
checked> &&
64 !std::is_same_v<std::decay_t<Args>, Dereferenceable>) && ...)))
67 : m_value(std::forward<Args>(args)...) {}
69 checked& operator=(
const Dereferenceable&
value) { m_value =
value;
return *
this; }
70 checked& operator=(Dereferenceable&&
value) noexcept(std::is_nothrow_move_assignable_v<Dereferenceable>) { m_value = std::move(
value);
return *
this; }
75 enforce<safety_level>(
static_cast<bool>(m_value),
"Attempted to dereference a null/empty value");
82 enforce<safety_level>(
static_cast<bool>(m_value),
"Attempted to dereference a null/empty value");
89 enforce<safety_level>(
static_cast<bool>(m_value),
"Attempted to dereference a null/empty value");
95 explicit operator bool() const noexcept {
return static_cast<bool>(m_value); }
103 return m_value.has_value();
107 constexpr decltype(
auto)
value() const
108 noexcept(noexcept(std::declval<const Dereferenceable&>().
value()))
111 return m_value.value();
116 noexcept(noexcept(std::declval<Dereferenceable&>().
value()))
119 return m_value.value();
123 template <
typename U>
125 noexcept(noexcept(std::declval<const Dereferenceable&>().
value_or(std::forward<U>(default_value))))
126 requires requires(
const Dereferenceable& v) { v.value_or(std::forward<U>(default_value)); }
128 return m_value.value_or(std::forward<U>(default_value));
132 template<
typename... Args>
133 void reset(Args&&... args) noexcept(noexcept(std::declval<Dereferenceable&>().
reset(std::forward<Args>(args)...)))
requires requires(Dereferenceable& v, Args&&... a) { v.reset(std::forward<Args>(a)...); }
135 m_value.reset(std::forward<Args>(args)...);
139 template<
class... Args>
142 return m_value.emplace(std::forward<Args>(args)...);
146 constexpr
const Dereferenceable&
unwrap() const & noexcept {
return m_value; }
147 constexpr Dereferenceable&
unwrap() & noexcept {
return m_value; }
148 constexpr Dereferenceable&&
unwrap() && noexcept {
return std::move(m_value); }
150 explicit constexpr
operator const Dereferenceable&()
const & noexcept {
return m_value; }
151 explicit constexpr
operator Dereferenceable&() & noexcept {
return m_value; }
152 explicit constexpr
operator Dereferenceable&&() && noexcept {
return std::move(m_value); }
155 template <
typename U>
158 requires { std::declval<const Dereferenceable&>() == rhs; }
160 return lhs.m_value == rhs;
165 requires requires { std::declval<const Dereferenceable&>() == std::declval<const Dereferenceable&>(); }
167 return lhs.m_value == rhs.m_value;
171 Dereferenceable m_value;
A generic wrapper for dereferenceable types (like pointers and optionals) that provides checked acces...
checked()=default
Default constructor.
constexpr auto value_or(U &&default_value) const noexcept(noexcept(std::declval< const Dereferenceable & >().value_or(std::forward< U >(default_value)))) requires requires(const Dereferenceable &v)
Returns the contained value or a default value if empty.
bool has_value() const noexcept(noexcept(std::declval< const Dereferenceable & >().has_value())) requires requires(const Dereferenceable &v)
Checks if the underlying object has a value.
auto get() const requires requires(const Dereferenceable &v)
Returns the raw underlying pointer/value without checks.
checked(Dereferenceable &&value) noexcept(std::is_nothrow_move_constructible_v< Dereferenceable >)
Move-constructs from a value.
auto & emplace(Args &&... args) requires requires(Dereferenceable &v
Constructs the underlying value in-place.
constexpr friend bool operator==(const checked &lhs, const checked &rhs) requires requires
Compares the underlying values of two checked wrappers.
constexpr decltype(auto) value() const noexcept(noexcept(std::declval< const Dereferenceable & >().value())) requires requires(const Dereferenceable &v)
Returns the value, potentially throwing if empty (forwarding underlying behavior).
void reset(Args &&... args) noexcept(noexcept(std::declval< Dereferenceable & >().reset(std::forward< Args >(args)...))) requires requires(Dereferenceable &v
Resets the underlying value.
constexpr friend bool operator==(const checked &lhs, const U &rhs) requires(!std
Compares the underlying value with another value.
auto operator->() const
Returns a pointer to the underlying value, checking for validity in strict mode.
checked(Args &&... args)
Forwards arguments to construct the underlying object in-place.
const auto & operator*() const
Returns a reference to the underlying value, checking for validity in strict mode.
auto & operator*()
Returns a reference to the underlying value, checking for validity in strict mode.
constexpr const Dereferenceable & unwrap() const &noexcept
Unwraps the checked wrapper to return the underlying object.
checked(const Dereferenceable &value)
Constructs from a value. Implicit conversion is allowed to support seamless wrapping of null-like typ...
The main namespace for the DocWire SDK.
requires(!string_method_equipped< T >) struct stringifier< T >
Specialization for types that are streamable to std::ostream.