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::kIsDetected
40struct NotDetected {};
41
42#if defined(__cpp_concepts) || defined(DOXYGEN)
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::kIsDetected<HasValueType, T>) { ... }
57/// @endcode
58template <template <typename...> typename Trait, typename... Args>
59concept kIsDetected = requires { typename Trait<Args...>; };
60
61#else
62
63template <template <typename...> typename Trait, typename... Args>
64inline constexpr bool kIsDetected = impl::Detector<NotDetected, void, Trait, Args...>::value_t::value;
65
66#endif
67
68/// @brief Produces the result type of a trait, or utils::meta::NotDetected if
69/// it's incorrect for the given template args
70/// @see utils::meta::kIsDetected
71template <template <typename...> typename Trait, typename... Args>
72using DetectedType = typename impl::Detector<NotDetected, void, Trait, Args...>::type;
73
74/// @brief Produces the result type of a trait, or @a Default if it's incorrect
75/// for the given template args
76/// @see utils::meta::kIsDetected
77template <typename Default, template <typename...> typename Trait, typename... Args>
78using DetectedOr = typename impl::Detector<Default, void, Trait, Args...>::type;
79
80/// Helps in definitions of traits for utils::meta::kIsDetected
81template <typename T, typename U>
82using ExpectSame = std::enable_if_t<std::is_same_v<T, U>>;
83
84/// Returns `true` if the type if an instantiation of the specified template.
85template <template <typename...> typename Template, typename T>
86inline constexpr bool kIsInstantiationOf = impl::IsInstantiationOf<Template, T>::value;
87
88/// Returns `true` if the type is a fundamental character type.
89/// `signed char` and `unsigned char` are not character types.
90template <typename T>
91inline constexpr bool kIsCharacter =
92 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>;
93
94/// Returns `true` if the type is a true integer type (not `*char*` or `bool`)
95/// `signed char` and `unsigned char` are integer types
96template <typename T>
97inline constexpr bool kIsInteger = std::is_integral_v<T> && !kIsCharacter<T> && !std::is_same_v<T, bool>;
98
99} // namespace meta
100
101USERVER_NAMESPACE_END