Akonadi

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

KDE's Doxygen guidelines are available online.