14#include <userver/utils/meta_light.hpp>
16USERVER_NAMESPACE_BEGIN
26using KeyType =
typename T::key_type;
29using MappedType =
typename T::mapped_type;
33 ExpectSame<std::decay_t<
decltype(begin(std::declval<T&>()))>, std::decay_t<
decltype(end(std::declval<T&>()))>>;
36using IteratorType = std::enable_if_t<IsDetected<IsRange, T>,
decltype(begin(std::declval<T&>()))>;
39using RangeValueType =
typename std::iterator_traits<DetectedType<IteratorType, T>>::value_type;
42using OstreamWriteResult =
decltype(std::declval<std::ostream&>() << std::declval<
const std::remove_reference_t<T>&>());
45using StdHashResult =
decltype(std::hash<T>{}(std::declval<
const T&>()));
48using AtResult =
decltype(std::declval<
const T&>().at(std::declval<
typename T::key_type>()));
51using SubscriptOperatorResult =
decltype(std::declval<T>()[std::declval<
typename T::key_type>()]);
54struct IsFixedSizeContainer : std::false_type {};
57template <
typename T, std::size_t Size,
template <
typename, std::size_t>
typename Array>
58struct IsFixedSizeContainer<Array<T, Size>> : std::bool_constant<
sizeof(Array<T, Size>) ==
sizeof(T) * Size> {};
60template <
typename... Args>
61constexpr bool IsSingleRange() {
62 if constexpr (
sizeof...(Args) == 1) {
63 return IsDetected<IsRange, Args...>;
74concept kIsVector = kIsInstantiationOf<std::vector, T>;
77concept kIsRange = IsDetected<impl::IsRange, T>;
81concept kIsMap = IsDetected<impl::IsRange, T> && IsDetected<impl::KeyType, T> && IsDetected<impl::MappedType, T>;
88 impl::SubscriptOperatorResult,
92using MapKeyType = DetectedType<impl::KeyType, T>;
95using MapValueType = DetectedType<impl::MappedType, T>;
98using RangeValueType = DetectedType<impl::RangeValueType, T>;
101concept kIsRecursiveRange = std::is_same_v<DetectedType<impl::RangeValueType, T>, T>;
104concept kIsIterator =
requires {
typename std::iterator_traits<T>::iterator_category; };
107concept kIsOptional = kIsInstantiationOf<std::optional, T>;
110concept kIsOstreamWritable = std::is_same_v<DetectedType<impl::OstreamWriteResult, T>, std::ostream&>;
112template <
typename T,
typename U = T>
113concept kIsEqualityComparable = std::equality_comparable_with<T, U>;
116concept kIsStdHashable = std::is_same_v<DetectedType<impl::StdHashResult, T>, std::size_t> && kIsEqualityComparable<T>;
120concept kIsSizable =
requires(T value) { std::size(value); };
124concept kIsReservable =
requires(T value) { value.reserve(1); };
128concept kIsPushBackable =
requires(T value) { value.push_back({}); };
132concept kIsFixedSizeContainer = impl::IsFixedSizeContainer<T>::value;
137 if constexpr (kIsPushBackable<T>) {
138 return std::back_inserter(container);
139 }
else if constexpr (kIsFixedSizeContainer<T>) {
140 return container.begin();
142 return std::inserter(container, container.end());