userver: userver/utils/meta_light.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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,
20 template <typename...> typename Trait, typename... Args>
21struct Detector {
22 using value_t = std::false_type;
23 using type = Default;
24};
25
26template <typename Default, template <typename...> typename Trait,
27 typename... Args>
28struct Detector<Default, utils::void_t<Trait<Args...>>, Trait, Args...> {
29 using value_t = std::true_type;
30 using type = Trait<Args...>;
31};
32
33template <template <typename...> typename Template, typename T>
34struct IsInstantiationOf : std::false_type {};
35
36template <template <typename...> typename Template, typename... Args>
37struct IsInstantiationOf<Template, Template<Args...>> : std::true_type {};
38
39} // namespace impl
40
41/// @see utils::meta::kIsDetected
42struct NotDetected {};
43
44#if defined(__cpp_concepts) || defined(DOXYGEN)
45
46/// @brief Checks whether a trait is correct for the given template args
47///
48/// Implements the pre-cpp20-concepts detection idiom.
49///
50/// To use, define a templated type alias (a "trait"), which for some type
51/// either is correct and produces ("detects") some result type,
52/// or is SFINAE-d out. Example:
53///
54/// @code
55/// template <typename T>
56/// using HasValueType = typename T::ValueType;
57/// ...
58/// if constexpr (utils::meta::kIsDetected<HasValueType, T>) { ... }
59/// @endcode
60template <template <typename...> typename Trait, typename... Args>
61concept kIsDetected = requires { typename Trait<Args...>; };
62
63#else
64
65template <template <typename...> typename Trait, typename... Args>
66inline constexpr bool kIsDetected =
67 impl::Detector<NotDetected, void, Trait, Args...>::value_t::value;
68
69#endif
70
71/// @brief Produces the result type of a trait, or utils::meta::NotDetected if
72/// it's incorrect for the given template args
73/// @see utils::meta::kIsDetected
74template <template <typename...> typename Trait, typename... Args>
75using DetectedType =
76 typename impl::Detector<NotDetected, void, Trait, Args...>::type;
77
78/// @brief Produces the result type of a trait, or @a Default if it's incorrect
79/// for the given template args
80/// @see utils::meta::kIsDetected
81template <typename Default, template <typename...> typename Trait,
82 typename... Args>
83using DetectedOr = typename impl::Detector<Default, void, Trait, Args...>::type;
84
85/// Helps in definitions of traits for utils::meta::kIsDetected
86template <typename T, typename U>
87using ExpectSame = std::enable_if_t<std::is_same_v<T, U>>;
88
89/// Returns `true` if the type if an instantiation of the specified template.
90template <template <typename...> typename Template, typename T>
91inline constexpr bool kIsInstantiationOf =
93
94/// Returns `true` if the type is a fundamental character type.
95/// `signed char` and `unsigned char` are not character types.
96template <typename T>
97inline constexpr bool kIsCharacter =
98 std::is_same_v<T, char> || std::is_same_v<T, wchar_t> ||
99 std::is_same_v<T, char16_t> || std::is_same_v<T, char32_t>;
100
101/// Returns `true` if the type is a true integer type (not `*char*` or `bool`)
102/// `signed char` and `unsigned char` are integer types
103template <typename T>
104inline constexpr bool kIsInteger =
105 std::is_integral_v<T> && !kIsCharacter<T> && !std::is_same_v<T, bool>;
106
107} // namespace meta
108
109USERVER_NAMESPACE_END