userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
meta.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/meta.hpp
4
/// @brief Metaprogramming, template variables and concepts
5
/// @ingroup userver_universal
6
7
#
include
<
concepts
>
8
#
include
<
iosfwd
>
9
#
include
<
iterator
>
10
#
include
<
optional
>
11
#
include
<
type_traits
>
12
#
include
<
utility
>
13
14
#
include
<
userver
/
compiler
/
impl
/
nodebug
.
hpp
>
15
#
include
<
userver
/
utils
/
meta_light
.
hpp
>
16
17
USERVER_NAMESPACE_BEGIN
18
19
/// @brief Metaprogramming utilities, concepts, and type traits helpers.
20
namespace
meta {
21
22
namespace
impl {
23
24
using
std::begin;
25
using
std::end;
26
27
template
<
typename
T>
28
concept
IsRange =
requires
(T& t) {
29
{
30
begin(t)
31
};
32
{
33
end(t)
34
};
35
};
36
37
template
<IsRange T>
38
using
IteratorType USERVER_IMPL_NODEBUG =
decltype
(begin(std::declval<T&>()));
39
40
template
<
typename
T>
41
using
RangeValueType USERVER_IMPL_NODEBUG =
typename
std::iterator_traits<IteratorType<T>>::value_type;
42
43
template
<
typename
T>
44
struct
IsFixedSizeContainer : std::false_type {};
45
46
// Boost and std arrays
47
template
<
typename
T, std::size_t Size,
template
<
typename
, std::size_t>
typename
Array>
48
struct
IsFixedSizeContainer<Array<T, Size>> : std::bool_constant<
sizeof
(Array<T, Size>) ==
sizeof
(T) * Size> {};
49
50
template
<
typename
... Args>
51
concept
IsSingleRange = (
sizeof
...(Args) == 1) && (impl::IsRange<Args> && ...);
52
53
}
// namespace impl
54
55
/// @warning Use std::ranges::range instead of this concept, except possibly in common headers
56
/// where compilation time is a concern.
57
template
<
typename
T>
58
concept
IsRange
= impl::IsRange<T>;
59
60
/// Returns true if T is an ordered or unordered map or multimap
61
template
<
typename
T>
62
concept
IsMap
=
IsRange
<T> &&
requires
{
63
typename
T::key_type;
64
typename
T::mapped_type;
65
};
66
67
/// Returns true if T is a map (but not a multimap!)
68
template
<
typename
T>
69
concept
IsUniqueMap
=
IsMap
<T> &&
requires
(T& map,
typename
T::key_type key) {
70
map[key];
// no operator[] in multimaps
71
};
72
73
template
<
IsMap
T>
74
using
MapKeyType =
typename
T::key_type;
75
76
template
<
IsMap
T>
77
using
MapValueType =
typename
T::mapped_type;
78
79
/// @warning Use std::ranges::range_value_t instead of this type, except possibly in common headers
80
/// where compilation time is a concern.
81
template
<
IsRange
T>
82
using
RangeValueType
= impl::RangeValueType<T>;
83
84
template
<
typename
T>
85
concept
IsRecursiveRange
=
IsRange
<T> && std::same_as<impl::RangeValueType<T>, T>;
86
87
template
<
typename
T>
88
concept
IsOptional
= kIsInstantiationOf<std::optional, T>;
89
90
template
<
typename
T>
91
concept
IsOstreamWritable
=
requires
(std::ostream& os,
const
std::remove_reference_t<T>& val) {
92
{
93
os << val
94
} -> std::same_as<std::ostream&>;
95
};
96
97
template
<
typename
T>
98
concept
IsStdHashable
=
requires
(
const
T& val) {
99
{
100
std::hash<T>{}(val)
101
} -> std::same_as<std::size_t>;
102
} && std::equality_comparable<T>;
103
104
/// @brief Check if std::size is applicable to container
105
/// @warning Use std::ranges::sized_range instead of this concept, except possibly in common headers
106
/// where compilation time is a concern.
107
template
<
typename
T>
108
concept
IsSizable
=
IsRange
<T> &&
requires
(T value) { std::size(value); };
109
110
/// @brief Check if a container has `reserve`
111
template
<
typename
T>
112
concept
IsReservable
=
IsSizable
<T> &&
requires
(T value) { value.reserve(1); };
113
114
/// @brief Check if a container has 'push_back'
115
template
<
typename
T>
116
concept
IsPushBackable
=
IsRange
<T> &&
requires
(T value,
RangeValueType
<T> element) {
117
value.push_back(std::move(element));
118
};
119
120
/// @brief Check if a container has fixed size (e.g. `std::array`)
121
template
<
typename
T>
122
concept
IsFixedSizeContainer
=
IsRange
<T> && impl::IsFixedSizeContainer<T>::value;
123
124
template
<
typename
T>
125
concept
IsVectorLike
=
IsRange
<T> && std::default_initializable<T> &&
IsReservable
<T> &&
IsPushBackable
<T>;
126
127
/// @brief Returns default inserter for a container
128
template
<
typename
T>
129
auto
Inserter
(T& container) {
130
if
constexpr
(
IsPushBackable
<T>) {
131
return
std::back_inserter(container);
132
}
else
if
constexpr
(
IsFixedSizeContainer
<T>) {
133
return
container.begin();
134
}
else
{
135
return
std::inserter(container, container.end());
136
}
137
}
138
139
/// @deprecated Use @ref meta::IsVectorLike instead.
140
template
<
typename
T>
141
// NOLINTNEXTLINE(readability-identifier-naming)
142
concept
kIsVector
=
IsVectorLike
<T>;
143
144
/// @deprecated Use @ref meta::IsRange instead.
145
template
<
typename
T>
146
// NOLINTNEXTLINE(readability-identifier-naming)
147
concept
kIsRange
=
IsRange
<T>;
148
149
/// @deprecated Use @ref meta::IsMap instead.
150
template
<
typename
T>
151
// NOLINTNEXTLINE(readability-identifier-naming)
152
concept
kIsMap
=
IsMap
<T>;
153
154
/// @deprecated Use @ref meta::IsOptional instead.
155
template
<
typename
T>
156
// NOLINTNEXTLINE(readability-identifier-naming)
157
concept
kIsOptional
=
IsOptional
<T>;
158
159
/// @deprecated Use @ref meta::IsSizable instead.
160
template
<
typename
T>
161
// NOLINTNEXTLINE(readability-identifier-naming)
162
concept
kIsSizable
=
IsSizable
<T>;
163
164
/// @deprecated Use @ref meta::IsReservable instead.
165
template
<
typename
T>
166
// NOLINTNEXTLINE(readability-identifier-naming)
167
concept
kIsReservable
=
IsReservable
<T>;
168
169
}
// namespace meta
170
171
USERVER_NAMESPACE_END
userver
utils
meta.hpp
Generated on
for userver by
Doxygen
1.17.0