14#include <userver/compiler/impl/nodebug.hpp>
15#include <userver/utils/meta_light.hpp>
17USERVER_NAMESPACE_BEGIN
28concept IsRange =
requires(T& t) {
38using IteratorType USERVER_IMPL_NODEBUG =
decltype(begin(std::declval<T&>()));
41using RangeValueType USERVER_IMPL_NODEBUG =
typename std::iterator_traits<IteratorType<T>>::value_type;
44struct IsFixedSizeContainer : std::false_type {};
47template <
typename T, std::size_t Size,
template <
typename, std::size_t>
typename Array>
48struct IsFixedSizeContainer<Array<T, Size>> : std::bool_constant<
sizeof(Array<T, Size>) ==
sizeof(T) * Size> {};
50template <
typename... Args>
51concept IsSingleRange = (
sizeof...(Args) == 1) && (impl::IsRange<Args> && ...);
58concept IsRange = impl::IsRange<T>;
62concept IsMap = IsRange<T> &&
requires {
64 typename T::mapped_type;
69concept IsUniqueMap = IsMap<T> &&
requires(T& map,
typename T::key_type key) {
74using MapKeyType =
typename T::key_type;
77using MapValueType =
typename T::mapped_type;
82using RangeValueType = impl::RangeValueType<T>;
85concept IsRecursiveRange = IsRange<T> && std::same_as<impl::RangeValueType<T>, T>;
88concept IsOptional = kIsInstantiationOf<std::optional, T>;
91concept IsOstreamWritable =
requires(std::ostream& os,
const std::remove_reference_t<T>& val) {
94 } -> std::same_as<std::ostream&>;
98concept IsStdHashable =
requires(
const T& val) {
101 } -> std::same_as<std::size_t>;
102} && std::equality_comparable<T>;
108concept IsSizable = IsRange<T> &&
requires(T value) { std::size(value); };
112concept IsReservable = IsSizable<T> &&
requires(T value) { value.reserve(1); };
116concept IsPushBackable = IsRange<T> &&
requires(T value, RangeValueType<T> element) {
117 value.push_back(std::move(element));
122concept IsFixedSizeContainer = IsRange<T> && impl::IsFixedSizeContainer<T>::value;
125concept IsVectorLike = IsRange<T> && std::default_initializable<T> && IsReservable<T> && IsPushBackable<T>;
130 if constexpr (IsPushBackable<T>) {
131 return std::back_inserter(container);
132 }
else if constexpr (IsFixedSizeContainer<T>) {
133 return container.begin();
135 return std::inserter(container, container.end());
142concept kIsVector = IsVectorLike<T>;
147concept kIsRange = IsRange<T>;
152concept kIsMap = IsMap<T>;
157concept kIsOptional = IsOptional<T>;
162concept kIsSizable = IsSizable<T>;
167concept kIsReservable = IsReservable<T>;