10#include <userver/formats/parse/to.hpp>
11#include <userver/formats/serialize/to.hpp>
12#include <userver/logging/log_helper_fwd.hpp>
13#include <userver/utils/assert.hpp>
15USERVER_NAMESPACE_BEGIN
21template <
typename Self,
typename... Args>
22inline constexpr bool kArgsAreNotSelf =
23 ((
sizeof...(Args) > 1) || ... || !std::is_same_v<std::decay_t<Args>, Self>);
25template <
bool Condition,
template <
typename...>
typename Trait,
27constexpr bool ConjunctionWithTrait()
noexcept {
28 if constexpr (Condition) {
29 return Trait<Args...>::value;
64 template <
typename U = T,
65 std::enable_if_t<impl::ConjunctionWithTrait<
68 impl::kArgsAreNotSelf<Box, U>,
72 std::is_convertible, U&&, T>(),
78 template <
typename... Args,
79 std::enable_if_t<impl::ConjunctionWithTrait<
82 impl::kArgsAreNotSelf<Box, Args...>,
84 std::is_constructible, T, Args&&...>(),
86 explicit Box(Args&&... args)
91 template <
typename Factory>
93 return Box(EmplaceFactory{}, std::forward<Factory>(factory));
96 Box(
Box&& other)
noexcept =
default;
97 Box& operator=(
Box&& other)
noexcept =
default;
99 Box(
const Box& other) : data_(std::make_unique<T>(*other)) {}
101 Box& operator=(
const Box& other) {
107 template <
typename U = T,
108 std::enable_if_t<impl::ConjunctionWithTrait<
109 impl::ConjunctionWithTrait<
112 impl::kArgsAreNotSelf<Box, U>,
114 std::is_constructible, T, U>(),
115 std::is_assignable, T&, U>(),
119 *data_ = std::forward<U>(other);
121 data_ = std::make_unique<T>(std::forward<U>(other));
127 operator
bool()
const =
delete;
129 T* operator->()
noexcept {
return Get(); }
130 const T* operator->()
const noexcept {
return Get(); }
132 T& operator*()
noexcept {
return *Get(); }
133 const T& operator*()
const noexcept {
return *Get(); }
135 bool operator==(
const Box& other)
const {
return **
this == *other; }
137 bool operator!=(
const Box& other)
const {
return **
this != *other; }
139 bool operator<(
const Box& other)
const {
return **
this < *other; }
141 bool operator>(
const Box& other)
const {
return **
this > *other; }
143 bool operator<=(
const Box& other)
const {
return **
this <= *other; }
145 bool operator>=(
const Box& other)
const {
return **
this >= *other; }
148 struct EmplaceFactory
final {};
150 template <
typename Factory>
151 explicit Box(EmplaceFactory, Factory&& factory)
152 : data_(
new T(std::forward<Factory>(factory)())) {}
159 const T* Get()
const noexcept {
164 std::unique_ptr<T> data_;
167template <
typename Value,
typename T>
168Box<T> Parse(
const Value& value, formats::
parse::
To<
Box<T>>) {
169 return Box<T>::MakeWithFactory([&value] {
return value.
template As<T>(); });
172template <
typename Value,
typename T>
173Value Serialize(
const Box<T>& value, formats::
serialize::
To<Value>) {
174 return Serialize(*value, formats::
serialize::
To<Value>{});
177template <
typename StringBuilder,
typename T>
178void WriteToStream(
const Box<T>& value, StringBuilder& sw) {
179 WriteToStream(*value, sw);