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,
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