Akonadi

aktraits.h
1 /*
2  SPDX-FileCopyrightText: 2019 Daniel Vr├ítil <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #include <type_traits>
10 #include <utility>
11 
12 namespace AkTraits
13 {
14 namespace detail
15 {
16 template<typename...> struct conjunction : std::true_type {
17 };
18 template<typename T> struct conjunction<T> : T {
19 };
20 template<typename T, typename... Ts> struct conjunction<T, Ts...> : std::conditional_t<bool(T::value), conjunction<Ts...>, T> {
21 };
22 
23 #define DECLARE_HAS_MEBER_TYPE(type_name) \
24  template<typename T, typename U = std::void_t<>> struct hasMember_##type_name { \
25  static constexpr bool value = false; \
26  }; \
27  \
28  template<typename T> struct hasMember_##type_name<T, std::void_t<typename T::type_name>> : std::true_type { \
29  };
30 
31 DECLARE_HAS_MEBER_TYPE(value_type)
32 
33 /// TODO: Use Boost TTI instead?
34 #define DECLARE_HAS_METHOD_GENERIC_IMPL(name, fun, sign) \
35  template<typename T, typename F = sign> struct hasMethod_##name { \
36  public: \
37  template<typename UType, UType> struct helperClass; \
38  \
39  using True = char; \
40  using False = struct { \
41  char dummy_[2]; \
42  }; \
43  \
44  template<typename U> static True helper(helperClass<F, &U::fun> *); \
45  template<typename> static False helper(...); \
46  \
47  public: \
48  static constexpr bool value = sizeof(helper<T>(nullptr)) == sizeof(True); \
49  };
50 
51 #define DECLARE_HAS_METHOD_GENERIC_CONST(fun, R, ...) DECLARE_HAS_METHOD_GENERIC_IMPL(fun##_const, fun, R (T::*)(__VA_ARGS__) const)
52 
53 #define DECLARE_HAS_METHOD_GENERIC(fun, R, ...) DECLARE_HAS_METHOD_GENERIC_IMPL(fun, fun, R (T::*)(__VA_ARGS__))
54 
55 // deal with Qt6 interface changes in QList::push_back/QList::insert
56 template<typename T, typename = std::void_t<>>
57 struct parameter_type {
58  typedef const typename T::value_type &type;
59 };
60 template<typename T>
61 struct parameter_type<T, std::void_t<typename T::parameter_type>> {
62  typedef typename T::parameter_type type;
63 };
64 
65 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
66 DECLARE_HAS_METHOD_GENERIC_CONST(size, int, void)
67 #else
68 DECLARE_HAS_METHOD_GENERIC_CONST(size, qsizetype, void)
69 #endif
70 DECLARE_HAS_METHOD_GENERIC(push_back, void, typename parameter_type<T>::type)
71 DECLARE_HAS_METHOD_GENERIC(insert, typename T::iterator, typename parameter_type<T>::type)
72 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
73 DECLARE_HAS_METHOD_GENERIC(reserve, void, int)
74 #else
75 DECLARE_HAS_METHOD_GENERIC(reserve, void, qsizetype)
76 #endif
77 
78 #define DECLARE_HAS_FUNCTION(name, fun) \
79  template<typename T> struct has_##name { \
80  template<typename U> struct helperClass; \
81  \
82  using True = char; \
83  using False = struct { \
84  char dummy_[2]; \
85  }; \
86  \
87  template<typename U> static True helper(helperClass<decltype(fun(std::declval<T>()))> *); \
88  template<typename> static False helper(...); \
89  \
90  public: \
91  static constexpr bool value = sizeof(helper<T>(nullptr)) == sizeof(True); \
92  };
93 
94 // For some obscure reason QVector::begin() actually has a default
95 // argument, but QList::begin() does not, thus a regular hasMethod_* check
96 // won't cut it here. Instead we check whether the container object can be
97 // used with std::begin() and std::end() helpers.
98 // Check for constness can be performed by passing "const T" to the type.
99 DECLARE_HAS_FUNCTION(begin, std::begin)
100 DECLARE_HAS_FUNCTION(end, std::end)
101 
102 /// This is a very incomplete set of Container named requirement, but I'm
103 /// too lazy to implement all of them, but this should be good enough to match
104 /// regular Qt containers and /not/ match arbitrary non-container types
105 template<typename T>
107  : conjunction<std::is_constructible<T>, hasMember_value_type<T>, has_begin<T>, has_begin<const T>, has_end<T>, has_end<const T>, hasMethod_size_const<T>> {
108 };
109 
110 /// Matches anything that is a container and has push_back() method.
111 template<typename T> struct isAppendable : conjunction<isContainer<T>, hasMethod_push_back<T>> {
112 };
113 
114 /// Matches anything that is a container and has insert() method.
115 template<typename T> struct isInsertable : conjunction<isContainer<T>, hasMethod_insert<T>> {
116 };
117 
118 /// Matches anything that is a container and has reserve() method.
119 template<typename T> struct isReservable : conjunction<isContainer<T>, hasMethod_reserve<T>> {
120 };
121 }
122 
123 template<typename T> constexpr bool isAppendable = detail::isAppendable<T>::value;
124 
125 template<typename T> constexpr bool isInsertable = detail::isInsertable<T>::value;
126 
127 template<typename T> constexpr bool isReservable = detail::isReservable<T>::value;
128 
129 } // namespace AkTraits
130 
131 #define AK_PP_CAT_(X, Y) X##Y
132 #define AK_PP_CAT(X, Y) AK_PP_CAT_(X, Y)
133 
134 #define AK_REQUIRES(...) bool AK_PP_CAT(_ak_requires_, __LINE__) = false, std::enable_if_t < AK_PP_CAT(_ak_requires_, __LINE__) || (__VA_ARGS__) > * = nullptr
135 
Matches anything that is a container and has reserve() method.
Definition: aktraits.h:119
Matches anything that is a container and has insert() method.
Definition: aktraits.h:115
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
A glue between Qt and the standard library.
Matches anything that is a container and has push_back() method.
Definition: aktraits.h:111
This is a very incomplete set of Container named requirement, but I'm too lazy to implement all of th...
Definition: aktraits.h:106
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Jun 27 2022 04:01:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.