swift
mixincompare.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_MIXIN_MIXINCOMPARE_H
7 #define SWIFT_MISC_MIXIN_MIXINCOMPARE_H
8 
9 #include <QList>
10 #include <QPair>
11 #include <QString>
12 
13 #include "misc/inheritancetraits.h"
14 #include "misc/metaclass.h"
15 #include "misc/typetraits.h"
16 
17 namespace swift::misc
18 {
19  class CEmpty;
20 
21  namespace mixin
22  {
23 
30  template <class Derived>
32  {
33  public:
35  friend bool operator==(const Derived &a, const Derived &b) { return compare(a, b) == 0; }
36 
38  friend bool operator!=(const Derived &a, const Derived &b) { return compare(a, b) != 0; }
39  };
40 
44  template <class Derived>
46  {
47  public:
49  friend bool operator==(const Derived &a, const Derived &b) { return equals(a, b); }
50 
52  friend bool operator!=(const Derived &a, const Derived &b) { return !equals(a, b); }
53 
54  private:
55  static bool equals(const Derived &a, const Derived &b);
56  template <typename T>
57  static bool baseEquals(const T *a, const T *b);
58  static bool baseEquals(const void *, const void *);
59  static bool baseEquals(const CEmpty *, const CEmpty *);
60  template <typename T, typename Flags>
61  static bool membersEqual(const T &a, const T &b, Flags);
62  };
63 
64  template <class Derived>
65  bool EqualsByMetaClass<Derived>::equals(const Derived &a, const Derived &b)
66  {
67  bool result =
68  baseEquals(static_cast<const TBaseOfT<Derived> *>(&a), static_cast<const TBaseOfT<Derived> *>(&b));
69  introspect<Derived>().forEachMember([&](auto member) {
70  if constexpr (!decltype(member)::has(MetaFlags<DisabledForComparison>()))
71  {
72  result = result && EqualsByMetaClass::membersEqual(member.in(a), member.in(b), member.m_flags);
73  }
74  });
75  return result;
76  }
77 
78  template <class Derived>
79  template <typename T>
80  bool EqualsByMetaClass<Derived>::baseEquals(const T *a, const T *b)
81  {
82  return *a == *b;
83  }
84 
85  template <class Derived>
86  bool EqualsByMetaClass<Derived>::baseEquals(const void *, const void *)
87  {
88  return true;
89  }
90 
91  template <class Derived>
92  bool EqualsByMetaClass<Derived>::baseEquals(const CEmpty *, const CEmpty *)
93  {
94  return true;
95  }
96 
97  template <class Derived>
98  template <typename T, typename Flags>
99  bool EqualsByMetaClass<Derived>::membersEqual(const T &a, const T &b, Flags)
100  {
101  if constexpr (static_cast<bool>(Flags::value & CaseInsensitiveComparison))
102  {
103  return a.compare(b, Qt::CaseInsensitive) == 0;
104  }
105  else { return a == b; }
106  }
107 
114  template <class Derived>
116  {
117  public:
119  friend bool operator<(const Derived &a, const Derived &b) { return compare(a, b) < 0; }
120 
122  friend bool operator>(const Derived &a, const Derived &b) { return compare(a, b) > 0; }
123 
125  friend bool operator<=(const Derived &a, const Derived &b) { return compare(a, b) <= 0; }
126 
128  friend bool operator>=(const Derived &a, const Derived &b) { return compare(a, b) >= 0; }
129  };
130 
134  template <class Derived>
136  {
137  public:
139  friend bool operator<(const Derived &a, const Derived &b) { return less(a, b); }
140 
142  friend bool operator>(const Derived &a, const Derived &b) { return less(b, a); }
143 
145  friend bool operator<=(const Derived &a, const Derived &b) { return !less(b, a); }
146 
148  friend bool operator>=(const Derived &a, const Derived &b) { return !less(a, b); }
149 
150  private:
151  static bool less(const Derived &a, const Derived &b);
152  template <typename T>
153  static bool baseLess(const T *a, const T *b);
154  static bool baseLess(const void *, const void *);
155  static bool baseLess(const CEmpty *, const CEmpty *);
156  template <typename T, typename Flags>
157  static bool membersLess(bool &io_greaterThan, const T &a, const T &b, Flags);
158  };
159 
160  template <class Derived>
161  bool LessThanByMetaClass<Derived>::less(const Derived &a, const Derived &b)
162  {
163  bool result =
164  baseLess(static_cast<const TBaseOfT<Derived> *>(&a), static_cast<const TBaseOfT<Derived> *>(&b));
165  bool gt = baseLess(static_cast<const TBaseOfT<Derived> *>(&b), static_cast<const TBaseOfT<Derived> *>(&a));
166  introspect<Derived>().forEachMember([&](auto member) {
167  if constexpr (!decltype(member)::has(MetaFlags<DisabledForComparison>()))
168  {
169  result = result || LessThanByMetaClass::membersLess(gt, member.in(a), member.in(b), member.m_flags);
170  }
171  });
172  return result;
173  }
174 
175  template <class Derived>
176  template <typename T>
177  bool LessThanByMetaClass<Derived>::baseLess(const T *a, const T *b)
178  {
179  return *a < *b;
180  }
181 
182  template <class Derived>
183  bool LessThanByMetaClass<Derived>::baseLess(const void *, const void *)
184  {
185  return false;
186  }
187 
188  template <class Derived>
189  bool LessThanByMetaClass<Derived>::baseLess(const CEmpty *, const CEmpty *)
190  {
191  return false;
192  }
193 
194  template <class Derived>
195  template <typename T, typename Flags>
196  bool LessThanByMetaClass<Derived>::membersLess(bool &io_greaterThan, const T &a, const T &b, Flags)
197  {
198  if (io_greaterThan) { return false; }
199  if constexpr (static_cast<bool>(Flags::value & CaseInsensitiveComparison))
200  {
201  io_greaterThan = b.compare(a, Qt::CaseInsensitive) < 0;
202  return a.compare(b, Qt::CaseInsensitive) < 0;
203  }
204  else
205  {
206  io_greaterThan = b < a;
207  return a < b;
208  }
209  }
210 
214  template <class Derived>
216  {
217  public:
219  friend int compare(const Derived &a, const Derived &b) { return compareImpl(a, b); }
220 
221  private:
222  static int compareImpl(const Derived &a, const Derived &b);
223  template <typename T>
224  static int baseCompare(const T *a, const T *b);
225  static int baseCompare(const void *, const void *);
226  static int baseCompare(const CEmpty *, const CEmpty *);
227  template <typename T, typename Flags>
228  static int membersCompare(const T &a, const T &b, Flags);
229  };
230 
231  template <class Derived>
232  int CompareByMetaClass<Derived>::compareImpl(const Derived &a, const Derived &b)
233  {
234  int result =
235  baseCompare(static_cast<const TBaseOfT<Derived> *>(&a), static_cast<const TBaseOfT<Derived> *>(&b));
236  introspect<Derived>().forEachMember([&](auto member) {
237  if constexpr (!decltype(member)::has(MetaFlags<DisabledForComparison>()))
238  {
239  result = result ? result :
240  CompareByMetaClass::membersCompare(member.in(a), member.in(b), member.m_flags);
241  }
242  });
243  return result;
244  }
245 
246  template <class Derived>
247  template <typename T>
248  int CompareByMetaClass<Derived>::baseCompare(const T *a, const T *b)
249  {
250  return compare(*a, *b);
251  }
252 
253  template <class Derived>
254  int CompareByMetaClass<Derived>::baseCompare(const void *, const void *)
255  {
256  return 0;
257  }
258 
259  template <class Derived>
260  int CompareByMetaClass<Derived>::baseCompare(const CEmpty *, const CEmpty *)
261  {
262  return 0;
263  }
264 
265  template <class Derived>
266  template <typename T, typename Flags>
267  int CompareByMetaClass<Derived>::membersCompare(const T &a, const T &b, Flags)
268  {
269  if constexpr (static_cast<bool>(Flags::value & CaseInsensitiveComparison))
270  {
271  return a.compare(b, Qt::CaseInsensitive);
272  }
273  else if constexpr (THasCompare<T, T>::value) { return compare(a, b); }
274  else { return a < b ? -1 : b < a ? 1 : 0; }
275  }
276 
277  } // namespace mixin
278 } // namespace swift::misc
279 
280 #endif // SWIFT_MISC_MIXIN_MIXINCOMPARE_H
Default base class for CValueObject.
Definition: valueobject.h:76
CRTP class template from which a derived class can inherit non-member compare() implemented by metacl...
Definition: mixincompare.h:216
friend int compare(const Derived &a, const Derived &b)
Return negative, zero, or positive if a is less than, equal to, or greater than b.
Definition: mixincompare.h:219
CRTP class template from which a derived class can inherit operator== implemented using its compare f...
Definition: mixincompare.h:32
friend bool operator!=(const Derived &a, const Derived &b)
Not equal.
Definition: mixincompare.h:38
friend bool operator==(const Derived &a, const Derived &b)
Equals.
Definition: mixincompare.h:35
CRTP class template from which a derived class can inherit operator== implemented by metaclass.
Definition: mixincompare.h:46
friend bool operator!=(const Derived &a, const Derived &b)
Not equal.
Definition: mixincompare.h:52
friend bool operator==(const Derived &a, const Derived &b)
Equals.
Definition: mixincompare.h:49
CRTP class template from which a derived class can inherit operator< implemented using its compare fu...
Definition: mixincompare.h:116
friend bool operator>(const Derived &a, const Derived &b)
Greater than.
Definition: mixincompare.h:122
friend bool operator<=(const Derived &a, const Derived &b)
Less than or equal.
Definition: mixincompare.h:125
friend bool operator<(const Derived &a, const Derived &b)
Less than.
Definition: mixincompare.h:119
friend bool operator>=(const Derived &a, const Derived &b)
Greater than or equal.
Definition: mixincompare.h:128
CRTP class template from which a derived class can inherit operator< implemented by metaclass.
Definition: mixincompare.h:136
friend bool operator>(const Derived &a, const Derived &b)
Greater than.
Definition: mixincompare.h:142
friend bool operator<=(const Derived &a, const Derived &b)
Less than or equal.
Definition: mixincompare.h:145
friend bool operator<(const Derived &a, const Derived &b)
Less than.
Definition: mixincompare.h:139
friend bool operator>=(const Derived &a, const Derived &b)
Greater than or equal.
Definition: mixincompare.h:148
int compare(T a, T b)
Compare arithmetic values.
@ CaseInsensitiveComparison
Element will be compared case insensitively (must be a QString)
Definition: metaclass.h:207
Free functions in swift::misc.
typename TBaseOf< T >::type TBaseOfT
Alias for typename TBaseOf<T>::type.
Type wrapper for passing MetaFlag to CMetaMember::has.
Definition: metaclass.h:119