13#include <rpp/defs.hpp>
14#include <rpp/utils/constraints.hpp>
15#include <rpp/utils/tuple.hpp>
28 template<
typename... Args>
33 template<constra
int::iterable T>
34 using iterable_value_t = std::iter_value_t<decltype(std::begin(std::declval<T>()))>;
38 template<
template<
typename...>
typename Base>
41 template<
typename... Types>
42 constexpr static rpp::utils::tuple<Types...> extract_params(
const Base<Types...>*);
43 constexpr static std::false_type extract_params(...);
47 template<
typename T,
template<
typename...>
typename Base>
48 concept is_base_of_v = !std::is_same_v<
decltype(details::traits<Base>::extract_params(std::declval<std::decay_t<T>*>())), std::false_type>;
50 template<
typename T,
template<
typename...>
typename Base>
52 using extract_base_type_params_t =
decltype(details::traits<Base>::extract_params(std::declval<std::decay_t<T>*>()));
55 constexpr std::add_const_t<T>& as_const(
const T& v)
noexcept
61 constexpr T&& as_const(T&& v)
noexcept
62 requires std::is_rvalue_reference_v<T&&>
64 return std::forward<T>(v);
67 struct convertible_to_any
69 convertible_to_any() =
default;
75 operator const T &()
const;
81 template<
typename Cont, std::invocable<iterable_value_t<Cont>> Fn>
82 void for_each(Cont&& container, Fn&& fn)
84 std::for_each(std::begin(container), std::end(container), std::forward<Fn>(fn));
87 template<
typename Cont, std::predicate<iterable_value_t<Cont>> Fn>
88 bool all_of(
const Cont& container,
const Fn& fn)
90 return std::all_of(std::cbegin(container), std::cend(container), fn);
93 template<auto Fn,
bool Inverse = false>
94 requires std::is_member_function_pointer_v<
decltype(Fn)>
98 requires (Inverse ==
false && std::invocable<
decltype(Fn), TT &&>)
99 auto operator()(TT&& d)
const
101 return (std::forward<TT>(d).*Fn)();
104 template<
typename TT>
105 requires (Inverse ==
true && std::invocable<
decltype(Fn), TT &&>)
106 auto operator()(TT&& d)
const
108 return !(std::forward<TT>(d).*Fn)();
118 template<std::invocable Fn>
122 explicit finally_action(Fn&& fn)
123 : m_fn{std::move(fn)}
127 explicit finally_action(
const Fn& fn)
132 finally_action(
const finally_action&) =
delete;
133 finally_action(finally_action&&)
noexcept =
delete;
135 ~finally_action()
noexcept { m_fn(); }
138 RPP_NO_UNIQUE_ADDRESS Fn m_fn;
141 template<rpp::constra
int::decayed_type T>
142 class repeated_container
145 repeated_container(T&& value,
size_t count)
146 : m_value{std::move(value)}
151 repeated_container(
const T& value,
size_t count)
160 iterator(
const repeated_container* container,
size_t index)
161 : m_container{container}
166 using iterator_category = std::input_iterator_tag;
167 using difference_type = std::ptrdiff_t;
168 using value_type = T;
171 const value_type& operator*()
const {
return m_container->m_value; }
173 iterator& operator++()
179 iterator operator++(
int)
186 bool operator==(
const iterator&)
const =
default;
187 bool operator!=(
const iterator&)
const =
default;
190 const repeated_container* m_container;
194 iterator begin()
const {
return {
this, 0}; }
196 iterator end()
const {
return {
this, m_count}; }
199 RPP_NO_UNIQUE_ADDRESS T m_value;
203 template<rpp::constra
int::decayed_type T>
204 class infinite_repeated_container
207 infinite_repeated_container(T&& value)
208 : m_value{std::move(value)}
212 infinite_repeated_container(
const T& value)
220 iterator(
const infinite_repeated_container* container)
221 : m_container{container}
225 using iterator_category = std::input_iterator_tag;
226 using difference_type = std::ptrdiff_t;
227 using value_type = T;
230 const value_type& operator*()
const {
return m_container->m_value; }
232 iterator& operator++() {
return *
this; }
234 iterator operator++(
int) {
return *
this; }
236 bool operator==(
const iterator&)
const =
default;
237 bool operator!=(
const iterator&)
const =
default;
240 const infinite_repeated_container* m_container;
243 iterator begin()
const {
return {
this}; }
245 iterator end()
const {
return {
nullptr}; }
248 RPP_NO_UNIQUE_ADDRESS T m_value;
253 static constexpr void lock() {}
254 static constexpr void unlock() {}
255 static constexpr void try_lock() {}
259 class value_with_mutex
262 value_with_mutex() =
default;
264 explicit value_with_mutex(
const T& v)
269 explicit value_with_mutex(T&& v)
270 : m_value{std::move(v)}
274 class pointer_under_lock
277 pointer_under_lock(value_with_mutex<T>&& value) =
delete;
279 pointer_under_lock(value_with_mutex<T>& value)
280 : pointer_under_lock{value.m_value, value.m_mutex}
285 pointer_under_lock(T& val, std::mutex& mutex)
292 T* operator->() {
return m_ptr; }
293 const T* operator->()
const {
return m_ptr; }
295 T& operator*() {
return *m_ptr; }
296 const T& operator*()
const {
return *m_ptr; }
300 std::scoped_lock<std::mutex> m_lock;
305 std::mutex& get_mutex() {
return m_mutex; }
306 T& get_value_unsafe() {
return m_value; }
309 RPP_NO_UNIQUE_ADDRESS T m_value{};
310 std::mutex m_mutex{};
318 template<
typename T,
typename... Ts>
323 template<
typename... Ts,
typename U,
typename... Us>
324 requires (std::is_same_v<U, Ts> || ...)
329 template<
typename... Ts,
typename U,
typename... Us>
335 template<
typename... Ts>
336 using unique_variant =
typename details::unique_variant_t<std::variant<>, Ts...>::type;
339#define RPP_CALL_DURING_CONSTRUCTION(...) RPP_NO_UNIQUE_ADDRESS rpp::utils::none _ = [&]() { \
341 return rpp::utils::none{}; \