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
11USERVER_NAMESPACE_BEGIN
12
13namespace meta {
14
15namespace impl {
16
17template <typename Default, template <typename...> typename Trait, typename... Args>
18struct Detector {
19 using type = Default;
20};
21
22template <typename Default, template <typename...> typename Trait, typename... Args>
23requires requires { typename Trait<Args...>; }
24struct Detector<Default, Trait, Args...> {
25 using type = Trait<Args...>;
26};
27
28template <template <typename...> typename Template, typename T>
29struct IsInstantiationOf : std::false_type {};
30
31template <template <typename...> typename Template, typename... Args>
32struct IsInstantiationOf<Template, Template<Args...>> : std::true_type {};
33
34} // namespace impl
35
36/// @see utils::meta::IsDetected
37struct NotDetected {};
38
39/// @brief Checks whether a trait is correct for the given template args
40///
41/// Implements the pre-cpp20-concepts detection idiom.
42///
43/// To use, define a templated type alias (a "trait"), which for some type
44/// either is correct and produces ("detects") some result type,
45/// or is SFINAE-d out. Example:
46///
47/// @code
48/// template <typename T>
49/// using HasValueType = typename T::ValueType;
50/// ...
51/// if constexpr (utils::meta::IsDetected<HasValueType, T>) { ... }
52/// @endcode
53///
54/// @deprecated Prefer using `requires` expressions directly in new code:
55/// @code
56/// if constexpr (requires { typename T::ValueType; }) { ... }
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, 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, Trait, Args...>::type;
72
73/// @brief Returns `true` if the type is an instantiation of the specified template.
74template <typename T, template <typename...> typename Template>
75concept IsInstantiationOf = impl::IsInstantiationOf<Template, T>::value;
76
77/// @brief Returns `true` if the type (with remove cv-qualifiers) is an instantiation of the specified template.
78template <typename T, template <typename...> typename Template>
79concept IsCvInstantiationOf = IsInstantiationOf<std::remove_cv_t<T>, Template>;
80
81/// Returns `true` if the type is a fundamental character type.
82/// `signed char` and `unsigned char` are not character types.
83template <typename T>
84concept IsCharacter =
85 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>;
86
87/// Returns `true` if the type is a true integer type (not `*char*` or `bool`)
88/// `signed char` and `unsigned char` are integer types
89template <typename T>
90concept IsInteger = std::is_integral_v<T> && !IsCharacter<T> && !std::is_same_v<T, bool>;
91
92/// @brief Returns `true` if the type is an instantiation of the specified template.
93/// @deprecated Use @ref meta::IsInstantiationOf instead.
94template <template <typename...> typename Template, typename T>
95// NOLINTNEXTLINE(readability-identifier-naming)
96concept kIsInstantiationOf = IsInstantiationOf<T, Template>;
97
98/// @brief Returns `true` if the type (with remove cv-qualifiers) is an instantiation of the specified template.
99/// @deprecated Use @ref meta::IsCvInstantiationOf instead.
100template <template <typename...> typename Template, typename T>
101// NOLINTNEXTLINE(readability-identifier-naming)
102concept kIsCvInstantiationOf = IsCvInstantiationOf<T, Template>;
103
104/// @brief Returns `true` if the type is a true integer type (not `*char*` or `bool`)
105/// `signed char` and `unsigned char` are integer types
106/// @deprecated Use @ref meta::IsInteger instead.
107template <typename T>
108// NOLINTNEXTLINE(readability-identifier-naming)
109concept kIsInteger = IsInteger<T>;
110
111} // namespace meta
112
113USERVER_NAMESPACE_END