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 = ((
sizeof...(Args) > 1) || ... || !std::is_same_v<std::decay_t<Args>, Self>);
24template <
bool Condition,
template <
typename...>
typename Trait,
typename... Args>
25constexpr bool ConjunctionWithTrait()
noexcept {
26 if constexpr (Condition) {
27 return Trait<Args...>::value;
60 : data_(std::make_unique<T>())
67 impl::ConjunctionWithTrait<
70 impl::kArgsAreNotSelf<
Box, U>,
79 : data_(std::make_unique<T>(std::forward<U>(arg)))
86 impl::ConjunctionWithTrait<
89 impl::kArgsAreNotSelf<
Box, Args...>,
91 std::is_constructible,
95 explicit Box(Args&&... args)
96 : data_(std::make_unique<T>(std::forward<Args>(args)...))
101 template <
typename Factory>
103 return Box(EmplaceFactory{}, std::forward<Factory>(factory));
106 Box(
Box&& other)
noexcept =
default;
107 Box& operator=(
Box&& other)
noexcept =
default;
109 Box(
const Box& other)
110 : data_(std::make_unique<T>(*other))
113 Box& operator=(
const Box& other) {
122 impl::ConjunctionWithTrait<
123 impl::ConjunctionWithTrait<
126 impl::kArgsAreNotSelf<
Box, U>,
128 std::is_constructible,
137 *data_ = std::forward<U>(other);
139 data_ = std::make_unique<T>(std::forward<U>(other));
145 operator
bool()
const =
delete;
147 T* operator->()
noexcept {
return Get(); }
148 const T* operator->()
const noexcept {
return Get(); }
150 T& operator*()
noexcept {
return *Get(); }
151 const T& operator*()
const noexcept {
return *Get(); }
153 bool operator==(
const Box& other)
const {
return **
this == *other; }
155 bool operator!=(
const Box& other)
const {
return **
this != *other; }
157 bool operator<(
const Box& other)
const {
return **
this < *other; }
159 bool operator>(
const Box& other)
const {
return **
this > *other; }
161 bool operator<=(
const Box& other)
const {
return **
this <= *other; }
163 bool operator>=(
const Box& other)
const {
return **
this >= *other; }
166 struct EmplaceFactory
final {};
168 template <
typename Factory>
169 explicit Box(EmplaceFactory, Factory&& factory)
170 : data_(
new T(std::forward<Factory>(factory)()))
174 UASSERT_MSG(data_,
"Accessing a moved-from Box");
178 const T* Get()
const noexcept {
179 UASSERT_MSG(data_,
"Accessing a moved-from Box");
183 std::unique_ptr<T> data_;
186template <
typename Value,
typename T>
187Box<T> Parse(
const Value& value, formats::parse::To<
Box<T>>) {
188 return Box<T>::MakeWithFactory([&value] {
return value.
template As<T>(); });
191template <
typename Value,
typename T>
192Value Serialize(
const Box<T>& value, formats::serialize::To<Value>) {
193 return Serialize(*value, formats::serialize::To<Value>{});
196template <
typename StringBuilder,
typename T>
197void WriteToStream(
const Box<T>& value, StringBuilder& sw) {
198 WriteToStream(*value, sw);
202logging::LogHelper& operator<<(logging::LogHelper& lh,
const Box<T>& box) {