14#include <userver/utils/meta_light.hpp>
16USERVER_NAMESPACE_BEGIN
26concept HasKeyType =
requires {
typename T::key_type; };
29concept HasMappedType =
requires {
typename T::mapped_type; };
32concept IsRange =
requires(T& t) {
33 requires std::is_same_v<std::decay_t<
decltype(begin(t))>, std::decay_t<
decltype(end(t))>>;
37using IteratorType =
decltype(begin(std::declval<T&>()));
40using RangeValueType =
typename std::iterator_traits<IteratorType<T>>::value_type;
43struct IsFixedSizeContainer : std::false_type {};
46template <
typename T, std::size_t Size,
template <
typename, std::size_t>
typename Array>
47struct IsFixedSizeContainer<Array<T, Size>> : std::bool_constant<
sizeof(Array<T, Size>) ==
sizeof(T) * Size> {};
49template <
typename... Args>
50concept IsSingleRange = (
sizeof...(Args) == 1) && (impl::IsRange<Args> && ...);
55concept IsVector = kIsInstantiationOf<std::vector, T>;
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) {
73template <impl::HasKeyType T>
74using MapKeyType =
typename T::key_type;
76template <impl::HasMappedType T>
77using MapValueType =
typename T::mapped_type;
79template <impl::IsRange T>
80using RangeValueType = impl::RangeValueType<T>;
83concept IsRecursiveRange = IsRange<T> && std::same_as<impl::RangeValueType<T>, T>;
86concept IsIterator =
requires {
typename std::iterator_traits<T>::iterator_category; };
89concept IsOptional = kIsInstantiationOf<std::optional, T>;
92concept IsOstreamWritable =
requires(std::ostream& os,
const std::remove_reference_t<T>& val) {
95 } -> std::same_as<std::ostream&>;
99concept IsStdHashable =
requires(
const T& val) {
102 } -> std::same_as<std::size_t>;
103} && std::equality_comparable<T>;
107concept IsSizable =
requires(T value) { std::size(value); };
111concept IsReservable =
requires(T value) { value.reserve(1); };
115concept IsPushBackable =
requires(T value) { value.push_back({}); };
119concept IsFixedSizeContainer = impl::IsFixedSizeContainer<T>::value;
124 if constexpr (IsPushBackable<T>) {
125 return std::back_inserter(container);
126 }
else if constexpr (IsFixedSizeContainer<T>) {
127 return container.begin();
129 return std::inserter(container, container.end());
136concept kIsVector = IsVector<T>;
141concept kIsRange = IsRange<T>;
146concept kIsMap = IsMap<T>;
151concept kIsOptional = IsOptional<T>;
156concept kIsSizable = IsSizable<T>;
161concept kIsReservable = IsReservable<T>;