userver: userver/utils/meta_light.hpp Source File
Loading...
Searching...
No Matches
meta_light.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/meta_light.hpp
4/// @brief Lightweight concepts
5/// @see userver/utils/meta.hpp for more concepts
6/// @ingroup userver_universal
7
8// Don't add new includes here! Put concepts that require them in meta.hpp.
9#include <type_traits>
10
11#include <userver/utils/void_t.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace meta {
16
17namespace impl {
18
19template <typename Default, typename AlwaysVoid, template <typename...> typename Trait, typename... Args>
20struct Detector {
21 using value_t = std::false_type;
22 using type = Default;
23};
24
25template <typename Default, template <typename...> typename Trait, typename... Args>
26struct Detector<Default, utils::void_t<Trait<Args...>>, Trait, Args...> {
27 using value_t = std::true_type;
28 using type = Trait<Args...>;
29};
30
31template <template <typename...> typename Template, typename T>
32struct IsInstantiationOf : std::false_type {};
33
34template <template <typename...> typename Template, typename... Args>
35struct IsInstantiationOf<Template, Template<Args...>> : std::true_type {};
36
37} // namespace impl
38
39/// @see utils::meta::IsDetected
40struct NotDetected {};
41
42// NOLINTBEGIN(readability-identifier-naming)
43
44/// @brief Checks whether a trait is correct for the given template args
45///
46/// Implements the pre-cpp20-concepts detection idiom.
47///
48/// To use, define a templated type alias (a "trait"), which for some type
49/// either is correct and produces ("detects") some result type,
50/// or is SFINAE-d out. Example:
51///
52/// @code
53/// template <typename T>
54/// using HasValueType = typename T::ValueType;
55/// ...
56/// if constexpr (utils::meta::IsDetected<HasValueType, T>) { ... }
57/// @endcode
58template <template <typename...> typename Trait, typename... Args>
59concept IsDetected = requires { typename Trait<Args...>; };
60
61/// @brief Produces the result type of a trait, or utils::meta::NotDetected if
62/// it's incorrect for the given template args
63/// @see utils::meta::IsDetected
64template <template <typename...> typename Trait, typename... Args>
65using DetectedType = typename impl::Detector<NotDetected, void, Trait, Args...>::type;
66
67/// @brief Produces the result type of a trait, or @a Default if it's incorrect
68/// for the given template args
69/// @see utils::meta::IsDetected
70template <typename Default, template <typename...> typename Trait, typename... Args>
71using DetectedOr = typename impl::Detector<Default, void, Trait, Args...>::type;
72
73/// Helps in definitions of traits for utils::meta::IsDetected
74template <typename T, typename U>
75using ExpectSame = std::enable_if_t<std::is_same_v<T, U>>;
76
77/// Returns `true` if the type is an instantiation of the specified template.
78template <template <typename...> typename Template, typename T>
79concept kIsInstantiationOf = impl::IsInstantiationOf<Template, T>::value;
80
81/// Returns `true` if the type (with remove cv-qualifiers) is an instantiation of the specified template.
82template <template <typename...> typename Template, typename T>
83concept kIsCvInstantiationOf = kIsInstantiationOf<Template, std::remove_cv_t<T>>;
84
85/// Returns `true` if the type is a fundamental character type.
86/// `signed char` and `unsigned char` are not character types.
87template <typename T>
88concept kIsCharacter =
89 std::is_same_v<T, char> || std::is_same_v<T, wchar_t> || std::is_same_v<T, char16_t> || std::is_same_v<T, char32_t>;
90
91/// Returns `true` if the type is a true integer type (not `*char*` or `bool`)
92/// `signed char` and `unsigned char` are integer types
93template <typename T>
94concept kIsInteger = std::is_integral_v<T> && !kIsCharacter<T> && !std::is_same_v<T, bool>;
95
96// NOLINTEND(readability-identifier-naming)
97
98} // namespace meta
99
100USERVER_NAMESPACE_END