Skip to content

Commit 043fe61

Browse files
committed
cc userver: use C++20 requires clause instead of std::enable_if_t
commit_hash:1fa571afee67adfc78ef513671961447b681d272
1 parent 3d6c652 commit 043fe61

38 files changed

Lines changed: 263 additions & 251 deletions

core/include/userver/baggage/baggage.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ std::optional<Baggage> TryMakeBaggage(std::string header, std::unordered_set<std
144144

145145
template <typename T>
146146
bool HasInvalidSymbols(const T& obj) {
147-
return std::find_if(obj.begin(), obj.end(), [](unsigned char x) {
147+
return std::ranges::find_if(obj, [](unsigned char x) {
148148
return x == ',' || x == ';' || x == '=' || std::isspace(x);
149149
}) != obj.end();
150150
}

core/include/userver/clients/http/request.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ class Request final {
329329

330330
/// @overload
331331
template <typename T>
332-
std::enable_if_t<std::is_same_v<ConnectTo, T>, Request&> connect_to(T&&) {
332+
requires std::is_same_v<ConnectTo, T>
333+
Request& connect_to(T&&) {
333334
static_assert(!sizeof(T), "ConnectTo argument must not be temporary, it must outlive Request");
334335
return *this;
335336
}

core/include/userver/components/container.hpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,13 @@ class Container;
2424

2525
namespace impl {
2626

27-
template <typename T, typename = void>
28-
struct ContainerHasName : std::false_type {};
29-
3027
template <typename T>
31-
struct ContainerHasName<T, utils::void_t<decltype(ContainerName(Of<T>()))>> : std::true_type {};
28+
concept ContainerHasName = requires { ContainerName(Of<T>{}); };
3229

3330
template <typename T>
3431
constexpr std::string_view GetContainerName()
3532
{
36-
if constexpr (ContainerHasName<T>::value) {
33+
if constexpr (ContainerHasName<T>) {
3734
return ContainerName(Of<T>());
3835
} else {
3936
static_assert(!sizeof(T), "Container name is not registered. Forgot to define ContainerName(Of<T>)?");
@@ -62,12 +59,14 @@ struct DependencyLocator {
6259
&& !!sizeof(LocateDependencyResult<T>) // 2) U is locate'able
6360
;
6461

65-
template <typename T, typename = std::enable_if_t<!kIsReference<T> && kIsLocatable<T>>>
62+
template <typename T>
63+
requires(!kIsReference<T> && kIsLocatable<T>)
6664
operator T() const {
6765
return LocateDependency(WithType<std::decay_t<T>>{}, config, context);
6866
}
6967

70-
template <typename T, typename = std::enable_if_t<kIsReference<T> && kIsLocatable<T>>>
68+
template <typename T>
69+
requires(kIsReference<T> && kIsLocatable<T>)
7170
operator T&() const {
7271
return LocateDependency(WithType<std::decay_t<T>>{}, config, context);
7372
}
@@ -93,21 +92,15 @@ T LocateDependency(WithType<T>, const ComponentConfig& config, const ComponentCo
9392
}
9493

9594
template <typename T>
96-
std::enable_if_t<impl::ContainerHasName<T>::value, T&> LocateDependency(
97-
WithType<T>,
98-
const ComponentConfig&,
99-
const ComponentContext& context
100-
)
95+
requires impl::ContainerHasName<T>
96+
T& LocateDependency(WithType<T>, const ComponentConfig&, const ComponentContext& context)
10197
{
10298
return context.FindComponent<Container<T>>().Get();
10399
}
104100

105101
template <typename T>
106-
std::enable_if_t<std::is_base_of_v<RawComponentBase, T>, T&> LocateDependency(
107-
WithType<T>,
108-
const ComponentConfig&,
109-
const ComponentContext& context
110-
)
102+
requires std::is_base_of_v<RawComponentBase, T>
103+
T& LocateDependency(WithType<T>, const ComponentConfig&, const ComponentContext& context)
111104
{
112105
return context.FindComponent<T>();
113106
}

core/include/userver/components/raw_component_base.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
/// @brief @copybrief components::RawComponentBase
55

66
#include <type_traits>
7-
#include <userver/utils/void_t.hpp>
87

98
USERVER_NAMESPACE_BEGIN
109

@@ -76,12 +75,12 @@ inline constexpr bool kForceNoValidation = false;
7675

7776
namespace impl {
7877

79-
template <typename Component, typename = void>
78+
template <typename Component>
8079
inline constexpr auto kDefaultConfigFileMode = ConfigFileMode::kRequired;
8180

8281
template <typename Component>
83-
inline constexpr auto
84-
kDefaultConfigFileMode<Component, utils::void_t<decltype(Component::kConfigFileMode)>> = Component::kConfigFileMode;
82+
requires requires { Component::kConfigFileMode; }
83+
inline constexpr auto kDefaultConfigFileMode<Component> = Component::kConfigFileMode;
8584
} // namespace impl
8685

8786
/// Specialize this to customize the loading of component settings

core/include/userver/dump/aggregates.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ T ReadAggregate(Reader& reader, std::index_sequence<Indices...>) {
6868
///
6969
/// @warning Don't forget to increment format-version if data layout changes
7070
template <typename T>
71-
std::enable_if_t<impl::IsDumpableAggregate<T>()> Write(Writer& writer, const T& value) {
71+
requires(impl::IsDumpableAggregate<T>())
72+
void Write(Writer& writer, const T& value) {
7273
boost::pfr::for_each_field(value, [&writer](const auto& field) { writer.Write(field); });
7374
}
7475

@@ -83,7 +84,8 @@ std::enable_if_t<impl::IsDumpableAggregate<T>()> Write(Writer& writer, const T&
8384
///
8485
/// @warning Don't forget to increment format-version if data layout changes
8586
template <typename T>
86-
std::enable_if_t<impl::IsDumpableAggregate<T>(), T> Read(Reader& reader, To<T>) {
87+
requires(impl::IsDumpableAggregate<T>())
88+
T Read(Reader& reader, To<T>) {
8789
constexpr auto kSize = boost::pfr::tuple_size_v<T>;
8890
return impl::ReadAggregate<T>(reader, std::make_index_sequence<kSize>{});
8991
}

core/include/userver/dump/common.hpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ void Write(Writer& writer, const char* value);
8484

8585
/// @brief Integral types serialization support
8686
template <typename T>
87-
std::enable_if_t<meta::kIsInteger<T>> Write(Writer& writer, T value) {
87+
requires meta::kIsInteger<T>
88+
void Write(Writer& writer, T value) {
8889
if constexpr (sizeof(T) == 1) {
8990
impl::WriteTrivial(writer, value);
9091
} else {
@@ -94,7 +95,8 @@ std::enable_if_t<meta::kIsInteger<T>> Write(Writer& writer, T value) {
9495

9596
/// @brief Integral types deserialization support
9697
template <typename T>
97-
std::enable_if_t<meta::kIsInteger<T>, T> Read(Reader& reader, To<T>) {
98+
requires meta::kIsInteger<T>
99+
T Read(Reader& reader, To<T>) {
98100
if constexpr (sizeof(T) == 1) {
99101
return impl::ReadTrivial<T>(reader);
100102
}
@@ -110,13 +112,15 @@ std::enable_if_t<meta::kIsInteger<T>, T> Read(Reader& reader, To<T>) {
110112

111113
/// @brief Floating-point serialization support
112114
template <typename T>
113-
std::enable_if_t<std::is_floating_point_v<T>> Write(Writer& writer, T value) {
115+
requires std::is_floating_point_v<T>
116+
void Write(Writer& writer, T value) {
114117
impl::WriteTrivial(writer, value);
115118
}
116119

117120
/// @brief Floating-point deserialization support
118121
template <typename T>
119-
std::enable_if_t<std::is_floating_point_v<T>, T> Read(Reader& reader, To<T>) {
122+
requires std::is_floating_point_v<T>
123+
T Read(Reader& reader, To<T>) {
120124
return impl::ReadTrivial<T>(reader);
121125
}
122126

@@ -128,13 +132,15 @@ bool Read(Reader& reader, To<bool>);
128132

129133
/// @brief enum serialization support
130134
template <typename T>
131-
std::enable_if_t<std::is_enum_v<T>> Write(Writer& writer, T value) {
135+
requires std::is_enum_v<T>
136+
void Write(Writer& writer, T value) {
132137
writer.Write(static_cast<std::underlying_type_t<T>>(value));
133138
}
134139

135140
/// @brief enum deserialization support
136141
template <typename T>
137-
std::enable_if_t<std::is_enum_v<T>, T> Read(Reader& reader, To<T>) {
142+
requires std::is_enum_v<T>
143+
T Read(Reader& reader, To<T>) {
138144
return static_cast<T>(reader.Read<std::underlying_type_t<T>>());
139145
}
140146

core/include/userver/dump/common_containers.hpp

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ VariantType ReadVariant(Reader& reader, std::size_t index) {
9393

9494
/// @brief Container serialization support
9595
template <typename T>
96-
std::enable_if_t<kIsContainer<T> && kIsWritable<meta::RangeValueType<T>>> Write(Writer& writer, const T& value) {
96+
requires(kIsContainer<T> && kIsWritable<meta::RangeValueType<T>>)
97+
void Write(Writer& writer, const T& value) {
9798
writer.Write(std::size(value));
9899
for (const auto& item : value) {
99100
// explicit cast for vector<bool> shenanigans
@@ -103,7 +104,8 @@ std::enable_if_t<kIsContainer<T> && kIsWritable<meta::RangeValueType<T>>> Write(
103104

104105
/// @brief Container deserialization support
105106
template <typename T>
106-
std::enable_if_t<kIsContainer<T> && kIsReadable<meta::RangeValueType<T>>, T> Read(Reader& reader, To<T>) {
107+
requires(kIsContainer<T> && kIsReadable<meta::RangeValueType<T>>)
108+
T Read(Reader& reader, To<T>) {
107109
const auto size = reader.Read<std::size_t>();
108110
T result{};
109111
if constexpr (meta::kIsReservable<T>) {
@@ -117,20 +119,23 @@ std::enable_if_t<kIsContainer<T> && kIsReadable<meta::RangeValueType<T>>, T> Rea
117119

118120
/// @brief Pair serialization support (for maps)
119121
template <typename T, typename U>
120-
std::enable_if_t<kIsWritable<T> && kIsWritable<U>, void> Write(Writer& writer, const std::pair<T, U>& value) {
122+
requires(kIsWritable<T> && kIsWritable<U>)
123+
void Write(Writer& writer, const std::pair<T, U>& value) {
121124
writer.Write(value.first);
122125
writer.Write(value.second);
123126
}
124127

125128
/// @brief Pair deserialization support (for maps)
126129
template <typename T, typename U>
127-
std::enable_if_t<kIsReadable<T> && kIsReadable<U>, std::pair<T, U>> Read(Reader& reader, To<std::pair<T, U>>) {
130+
requires(kIsReadable<T> && kIsReadable<U>)
131+
std::pair<T, U> Read(Reader& reader, To<std::pair<T, U>>) {
128132
return {reader.Read<T>(), reader.Read<U>()};
129133
}
130134

131135
/// @brief `std::optional` serialization support
132136
template <typename T>
133-
std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const std::optional<T>& value) {
137+
requires kIsWritable<T>
138+
void Write(Writer& writer, const std::optional<T>& value) {
134139
writer.Write(value.has_value());
135140
if (value) {
136141
writer.Write(*value);
@@ -139,7 +144,8 @@ std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const std::optional<T>& v
139144

140145
/// @brief `std::optional` deserialization support
141146
template <typename T>
142-
std::enable_if_t<kIsReadable<T>, std::optional<T>> Read(Reader& reader, To<std::optional<T>>) {
147+
requires kIsReadable<T>
148+
std::optional<T> Read(Reader& reader, To<std::optional<T>>) {
143149
if (!reader.Read<bool>()) {
144150
return std::nullopt;
145151
}
@@ -148,15 +154,16 @@ std::enable_if_t<kIsReadable<T>, std::optional<T>> Read(Reader& reader, To<std::
148154

149155
/// @brief `std::variant` serialization support
150156
template <typename... Args>
151-
std::enable_if_t<(true && ... && kIsWritable<Args>)> Write(Writer& writer, const std::variant<Args...>& value) {
157+
requires(true && ... && kIsWritable<Args>)
158+
void Write(Writer& writer, const std::variant<Args...>& value) {
152159
writer.Write(value.index());
153160
std::visit([&writer](const auto& inner) { writer.Write(inner); }, value);
154161
}
155162

156163
/// @brief `std::variant` deserialization support
157164
template <typename... Args>
158-
std::enable_if_t<(true && ... && (std::is_move_constructible_v<Args> && kIsReadable<Args>)), std::variant<Args...>>
159-
Read(Reader& reader, To<std::variant<Args...>>) {
165+
requires(true && ... && (std::is_move_constructible_v<Args> && kIsReadable<Args>))
166+
std::variant<Args...> Read(Reader& reader, To<std::variant<Args...>>) {
160167
const auto index = reader.Read<std::size_t>();
161168
if (index >= sizeof...(Args)) {
162169
impl::ThrowInvalidVariantIndex(typeid(std::variant<Args...>), index);
@@ -167,26 +174,29 @@ Read(Reader& reader, To<std::variant<Args...>>) {
167174
/// Allows reading `const T`, which is usually encountered as a member of some
168175
/// container
169176
template <typename T>
170-
std::enable_if_t<kIsReadable<T>, T> Read(Reader& reader, To<const T>) {
177+
requires kIsReadable<T>
178+
T Read(Reader& reader, To<const T>) {
171179
return Read(reader, To<T>{});
172180
}
173181

174182
/// @brief utils::StrongTypedef serialization support
175183
template <typename Tag, typename T, utils::StrongTypedefOps Ops>
176-
std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const utils::StrongTypedef<Tag, T, Ops>& object) {
184+
requires kIsWritable<T>
185+
void Write(Writer& writer, const utils::StrongTypedef<Tag, T, Ops>& object) {
177186
writer.Write(object.GetUnderlying());
178187
}
179188

180189
/// @brief utils::StrongTypedef deserialization support
181190
template <typename Tag, typename T, utils::StrongTypedefOps Ops>
182-
std::enable_if_t<kIsReadable<T>, utils::StrongTypedef<Tag, T, Ops>>
183-
Read(Reader& reader, To<utils::StrongTypedef<Tag, T, Ops>>) {
191+
requires kIsReadable<T>
192+
utils::StrongTypedef<Tag, T, Ops> Read(Reader& reader, To<utils::StrongTypedef<Tag, T, Ops>>) {
184193
return utils::StrongTypedef<Tag, T, Ops>{reader.Read<T>()};
185194
}
186195

187196
/// @brief `std::unique_ptr` serialization support
188197
template <typename T>
189-
std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const std::unique_ptr<T>& ptr) {
198+
requires kIsWritable<T>
199+
void Write(Writer& writer, const std::unique_ptr<T>& ptr) {
190200
writer.Write(static_cast<bool>(ptr));
191201
if (ptr) {
192202
writer.Write(*ptr);
@@ -195,7 +205,8 @@ std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const std::unique_ptr<T>&
195205

196206
/// @brief `std::unique_ptr` deserialization support
197207
template <typename T>
198-
std::enable_if_t<kIsReadable<T>, std::unique_ptr<T>> Read(Reader& reader, To<std::unique_ptr<T>>) {
208+
requires kIsReadable<T>
209+
std::unique_ptr<T> Read(Reader& reader, To<std::unique_ptr<T>>) {
199210
if (!reader.Read<bool>()) {
200211
return {};
201212
}
@@ -206,7 +217,8 @@ std::enable_if_t<kIsReadable<T>, std::unique_ptr<T>> Read(Reader& reader, To<std
206217
/// @warning If two or more `shared_ptr` within a single dumped entity point to
207218
/// the same object, they will point to its distinct copies after loading a dump
208219
template <typename T>
209-
std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const std::shared_ptr<T>& ptr) {
220+
requires kIsWritable<T>
221+
void Write(Writer& writer, const std::shared_ptr<T>& ptr) {
210222
writer.Write(static_cast<bool>(ptr));
211223
if (ptr) {
212224
writer.Write(*ptr);
@@ -217,7 +229,8 @@ std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const std::shared_ptr<T>&
217229
/// @warning If two or more `shared_ptr` within a single dumped entity point to
218230
/// the same object, they will point to its distinct copies after loading a dump
219231
template <typename T>
220-
std::enable_if_t<kIsReadable<T>, std::shared_ptr<T>> Read(Reader& reader, To<std::shared_ptr<T>>) {
232+
requires kIsReadable<T>
233+
std::shared_ptr<T> Read(Reader& reader, To<std::shared_ptr<T>>) {
221234
if (!reader.Read<bool>()) {
222235
return {};
223236
}
@@ -226,9 +239,8 @@ std::enable_if_t<kIsReadable<T>, std::shared_ptr<T>> Read(Reader& reader, To<std
226239

227240
/// @brief `boost::bimap` serialization support
228241
template <typename L, typename R, typename... Args>
229-
std::enable_if_t<
230-
kIsWritable<impl::BoostBimapLeftKey<L, R, Args...>> && kIsWritable<impl::BoostBimapRightKey<L, R, Args...>>>
231-
Write(Writer& writer, const boost::bimap<L, R, Args...>& map) {
242+
requires(kIsWritable<impl::BoostBimapLeftKey<L, R, Args...>> && kIsWritable<impl::BoostBimapRightKey<L, R, Args...>>)
243+
void Write(Writer& writer, const boost::bimap<L, R, Args...>& map) {
232244
writer.Write(map.size());
233245

234246
for (const auto& [left, right] : map) {
@@ -239,10 +251,8 @@ Write(Writer& writer, const boost::bimap<L, R, Args...>& map) {
239251

240252
/// @brief `boost::bimap` deserialization support
241253
template <typename L, typename R, typename... Args>
242-
std::enable_if_t<
243-
kIsReadable<impl::BoostBimapLeftKey<L, R, Args...>> && kIsReadable<impl::BoostBimapRightKey<L, R, Args...>>,
244-
boost::bimap<L, R, Args...>>
245-
Read(Reader& reader, To<boost::bimap<L, R, Args...>>) {
254+
requires(kIsReadable<impl::BoostBimapLeftKey<L, R, Args...>> && kIsReadable<impl::BoostBimapRightKey<L, R, Args...>>)
255+
boost::bimap<L, R, Args...> Read(Reader& reader, To<boost::bimap<L, R, Args...>>) {
246256
using BoostBimap = impl::BoostBimap<L, R, Args...>;
247257

248258
using BoostBimapLeftKey = impl::BoostBimapLeftKey<L, R, Args...>;
@@ -267,7 +277,8 @@ Read(Reader& reader, To<boost::bimap<L, R, Args...>>) {
267277

268278
/// @brief `boost::multi_index_container` serialization support
269279
template <typename T, typename Index, typename Alloc>
270-
std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const boost::multi_index_container<T, Index, Alloc>& container) {
280+
requires kIsWritable<T>
281+
void Write(Writer& writer, const boost::multi_index_container<T, Index, Alloc>& container) {
271282
writer.Write(container.template get<0>().size());
272283
for (auto& item : container.template get<0>()) {
273284
writer.Write(item);
@@ -276,8 +287,8 @@ std::enable_if_t<kIsWritable<T>> Write(Writer& writer, const boost::multi_index_
276287

277288
/// @brief `boost::multi_index_container` deserialization support
278289
template <typename T, typename Index, typename Alloc>
279-
std::enable_if_t<kIsReadable<T>, boost::multi_index_container<T, Index, Alloc>>
280-
Read(Reader& reader, To<boost::multi_index_container<T, Index, Alloc>>) {
290+
requires kIsReadable<T>
291+
boost::multi_index_container<T, Index, Alloc> Read(Reader& reader, To<boost::multi_index_container<T, Index, Alloc>>) {
281292
const auto size = reader.Read<std::size_t>();
282293
boost::multi_index_container<T, Index, Alloc> container;
283294

core/include/userver/dynamic_config/storage_mock.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace dynamic_config {
1919
namespace impl {
2020

2121
template <typename T>
22-
using IsJson = std::enable_if_t<std::is_same_v<T, formats::json::Value>>;
22+
concept IsJson = std::is_same_v<T, formats::json::Value>;
2323

2424
} // namespace impl
2525

core/include/userver/server/handlers/exceptions.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ class CustomHandlerException : public std::runtime_error {
269269
{}
270270

271271
/// @deprecated Use the variadic constructor above instead.
272-
template <typename MessageBuilder, typename = std::enable_if_t<impl::kIsMessageBuilder<MessageBuilder>>>
272+
template <typename MessageBuilder>
273+
requires impl::kIsMessageBuilder<MessageBuilder>
273274
CustomHandlerException(MessageBuilder&& builder, HandlerErrorCode handler_code)
274275
: CustomHandlerException(impl::CustomHandlerExceptionData{std::forward<MessageBuilder>(builder), handler_code})
275276
{}

0 commit comments

Comments
 (0)