KItinerary

datatypes_impl.h
1/*
2 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#pragma once
8
9#include "internal/instance_counter.h"
10#include "internal/parameter_type.h"
11#include "internal/strict_equal.h"
12#include "internal/strict_less.h"
13
14namespace KItinerary {
15
16///@cond internal
17namespace detail {
18
19// SFINAE helper to determine if we have a polymorphic or a simple value type
20template <typename T>
21struct base_type {
22 template <typename U> static typename U::super_type test(typename U::super_type*);
23 template <typename U> static T test(...);
24 using type = decltype(test<T>(nullptr));
25 static constexpr const bool is_valid = !std::is_same<type, T>::value;
26};
27}
28
29#define KITINERARY_MAKE_CLASS_IMPL(Class) \
30Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<Class ## Private>, s_ ## Class ## _shared_null, (new Class ## Private)) \
31Class::Class() : Class(s_ ## Class ## _shared_null()->data()) {} \
32Class::Class(const Class&) = default; \
33Class::~Class() = default; \
34Class& Class::operator=(const Class &other) { d = other.d; return *this; } \
35QString Class::className() const { return QStringLiteral(#Class); } \
36Class::operator QVariant() const { return QVariant::fromValue(*this); } \
37const char* Class::typeName() { return #Class; } \
38static_assert(sizeof(Class) == sizeof(void*), "dptr must be the only member!"); \
39namespace detail { \
40 static constexpr int property_counter(KItinerary::detail::num<0>, KItinerary::detail::tag<Class>) \
41 { return 1; } \
42 static constexpr bool property_equals(KItinerary::detail::num<0>, KItinerary::detail::tag<Class ## Private>, const Class ## Private *, const Class ## Private *) \
43 { return true; } \
44 static constexpr bool property_less(KItinerary::detail::num<0>, KItinerary::detail::tag<Class ## Private>, const Class ## Private *, const Class ## Private *) \
45 { return true; } \
46}
47///@endcond
48
49/** Macro to generate the value type and introspection implementation for a vocabulary type.
50 * This provides the implementation of KITINERARY_GADGET.
51 */
52#define KITINERARY_MAKE_CLASS(Class) \
53KITINERARY_MAKE_CLASS_IMPL(Class) \
54Class::Class(Class ## Private *dd) : d(dd) {}
55
56/** Macro to generate the value type and introspection implementation for a derived vocabulary type.
57 * This provides the implementation of KITINERARY_GADGET.
58 */
59#define KITINERARY_MAKE_DERIVED_CLASS(Class, Base) \
60KITINERARY_MAKE_CLASS_IMPL(Class) \
61Class::Class(Class ## Private *dd) : Base(dd) {}
62
63/** Macros to generate operator implementation details for a property.
64 * This is not needed when using KITINERARY_MAKE_PROPERTY, but only when
65 * implementing getters/setters manually.
66 */
67#define KITINERARY_MAKE_PROPERTY_OPERATOR(Class, Type, Name) \
68namespace detail { \
69 static constexpr int property_counter(KItinerary::detail::num<property_counter(KItinerary::detail::num<>(), KItinerary::detail::tag<Class>())> n, KItinerary::detail::tag<Class>) \
70 { return decltype(n)::value + 1; } \
71 static inline bool property_equals(KItinerary::detail::num<property_counter(KItinerary::detail::num<>(), KItinerary::detail::tag<Class>())> n, KItinerary::detail::tag<Class ## Private>, const Class ## Private *lhs, const Class ## Private *rhs) \
72 { \
73 if (KItinerary::detail::strict_equal<Type>(lhs->Name, rhs->Name)) { \
74 return property_equals(n.prev(), KItinerary::detail::tag<Class ## Private>(), lhs, rhs); \
75 } \
76 return false; \
77 } \
78 static inline bool property_less(KItinerary::detail::num<property_counter(KItinerary::detail::num<>(), KItinerary::detail::tag<Class>())> n, KItinerary::detail::tag<Class ## Private>, const Class ## Private *lhs, const Class ## Private *rhs) \
79 { \
80 if (KItinerary::detail::strict_less<Type>(lhs->Name, rhs->Name)) { return true; } \
81 if (KItinerary::detail::strict_equal<Type>(lhs->Name, rhs->Name)) { \
82 return property_less(n.prev(), KItinerary::detail::tag<Class ## Private>(), lhs, rhs); \
83 } \
84 return false; \
85 } \
86}
87
88/** Macro to generate the implementation of a vocabulary property type.
89 * This generates the definitions for the declaration the KITINERARY_PROPERTY macro
90 * produces, as well as implementation details needed for the automatic comparison
91 * operator.
92 * @see KITINERARY_MAKE_OPERATOR
93 */
94#define KITINERARY_MAKE_PROPERTY(Class, Type, Name, SetName) \
95Type Class::Name() const { return static_cast<const Class ## Private*>(d.data())->Name; } \
96void Class::SetName(KItinerary::detail::parameter_type<Type>::type value) { \
97 if (KItinerary::detail::strict_equal<Type>(static_cast<Class ## Private*>(d.data())->Name, value)) { return; } \
98 d.detach(); \
99 static_cast<Class ## Private*>(d.data())->Name = value; \
100} \
101KITINERARY_MAKE_PROPERTY_OPERATOR(Class, Type, Name)
102
103/** Generates the implementation of the comparison operator for vocabulary type @p Class.
104 * The generated operator==() implementation will check all properties for strict equality,
105 * as well as call operator==() of a base class if present.
106 * This relies on KITINERARY_MAKE_PROPERTY to generate supporting code and thus has to be
107 * called after all properties have been generated.
108 */
109#define KITINERARY_MAKE_OPERATOR(Class) \
110namespace detail { \
111static inline bool recursive_less(KItinerary::detail::tag<Class ## Private>, const Class ## Private *lhs, const Class ## Private *rhs) { \
112 if constexpr (KItinerary::detail::base_type<Class ## Private>::is_valid) { \
113 if (detail::property_equals(KItinerary::detail::num<>(), KItinerary::detail::tag<Class ## Private>(), lhs, rhs)) { \
114 typedef typename KItinerary::detail::base_type<Class ## Private>::type super_type; \
115 if (detail::property_less(KItinerary::detail::num<>(), KItinerary::detail::tag<super_type>(), static_cast<const super_type*>(lhs), static_cast<const super_type*>(rhs))) { return true; } \
116 return recursive_less(KItinerary::detail::tag<super_type>(), static_cast<const super_type*>(lhs), static_cast<const super_type*>(rhs)); \
117 } \
118 } \
119 return false; \
120} \
121static inline bool recursive_equal(KItinerary::detail::tag<Class ## Private>, const Class ## Private *lhs, const Class ## Private *rhs) { \
122 if constexpr (KItinerary::detail::base_type<Class ## Private>::is_valid) { \
123 typedef typename KItinerary::detail::base_type<Class ## Private>::type super_type; \
124 if (!detail::property_equals(KItinerary::detail::num<>(), KItinerary::detail::tag<super_type>(), static_cast<const super_type*>(lhs), static_cast<const super_type*>(rhs))) { return false; } \
125 return recursive_equal(KItinerary::detail::tag<super_type>(), static_cast<const super_type*>(lhs), static_cast<const super_type*>(rhs)); \
126 } \
127 return true; \
128} \
129} \
130bool Class::operator<(const Class &other) const { \
131 static_assert(detail::property_counter(KItinerary::detail::num<0>(), KItinerary::detail::tag<Class>()) == 1, "silence unused function warnings"); \
132 typedef Class ## Private this_type; \
133 const auto lhs = static_cast<const this_type *>(d.data()); \
134 const auto rhs = static_cast<const this_type*>(other.d.data()); \
135 if (lhs == rhs) { \
136 return false; \
137 } \
138 if (detail::property_less(KItinerary::detail::num<>(), KItinerary::detail::tag<this_type>(), lhs, rhs)) { \
139 return true; \
140 } \
141 return detail::recursive_less(KItinerary::detail::tag<this_type>(), lhs, rhs); \
142} \
143bool Class::operator==(const Class &other) const \
144{ \
145 static_assert(detail::property_counter(KItinerary::detail::num<0>(), KItinerary::detail::tag<Class>()) == 1, "silence unused function warnings"); \
146 typedef Class ## Private this_type; \
147 const auto lhs = static_cast<const this_type *>(d.data()); \
148 const auto rhs = static_cast<const this_type*>(other.d.data()); \
149 if (lhs == rhs) { \
150 return true; \
151 } \
152 if (!detail::property_equals(KItinerary::detail::num<>(), KItinerary::detail::tag<this_type>(), lhs, rhs)) { \
153 return false; \
154 } \
155 return detail::recursive_equal(KItinerary::detail::tag<this_type>(), lhs, rhs); \
156}
157
158}
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
KGuiItem test()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:09:58 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.