IMP logo
IMP Reference Guide  develop.374319d7bb,2024/06/17
The Integrative Modeling Platform
comparison_macros.h
Go to the documentation of this file.
1 /**
2  * \file IMP/comparison_macros.h
3  * \brief Helper macros for implementing comparisons of \imp objects
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_COMPARISON_MACROS_H
10 #define IMPKERNEL_COMPARISON_MACROS_H
11 #include <IMP/kernel_config.h>
12 #include "warning_macros.h"
13 
14 #if defined(IMP_DOXYGEN)
15 /** \name Comparisons
16  Helper macros for implementing comparisons in terms of
17  either member variables or a member compare function.
18  All of the <,>,== etc are implemented for both C++
19  and Python.
20  @{
21 */
22 
23 //! Implement comparison in a class using a compare function
24 /** The compare function should take a const Name & and return -1, 0, 1 as
25  appropriate.
26 */
27 #define IMP_COMPARISONS(Name)
28 
29 //! Implement comparison in a class using field as the variable to compare
30 /** \param[in] Name the name of the class
31  \param[in] field the first field to compare on
32  */
33 #define IMP_COMPARISONS_1(Name, field)
34 
35 //! Implement comparison in a class using field as the variable to compare
36 /** \param[in] Name the name of the class
37  \param[in] f0 the first field to compare on
38  \param[in] f1 the second field to compare on
39  */
40 #define IMP_COMPARISONS_2(Name, f0, f1)
41 
42 //! Implement comparison in a class using field as the variable to compare
43 /** \param[in] Name the name of the class
44  \param[in] f0 the first field to compare on
45  \param[in] f1 the second field to compare on
46  \param[in] f2 the third field to compare on
47  */
48 #define IMP_COMPARISONS_3(Name, f0, f1, f2)
49 /** @} */
50 #elif defined(SWIG)
51 #define IMP_SWIG_COMPARISONS(Name) \
52  int __cmp__(const Name& o) const; \
53  bool __eq__(const Name& o) const; \
54  bool __ne__(const Name& o) const; \
55  bool __lt__(const Name& o) const; \
56  bool __gt__(const Name& o) const; \
57  bool __ge__(const Name& o) const; \
58  bool __le__(const Name& o) const
59 
60 #define IMP_COMPARISONS(Name) IMP_SWIG_COMPARISONS(Name)
61 
62 #define IMP_COMPARISONS_1(Name, field) IMP_SWIG_COMPARISONS(Name)
63 
64 #define IMP_COMPARISONS_2(Name, f0, f1) IMP_SWIG_COMPARISONS(Name)
65 
66 #define IMP_COMPARISONS_3(Name, f0, f1, f2) IMP_SWIG_COMPARISONS(Name)
67 
68 #else // not doxygen
69 #define IMP_SWIG_COMPARISONS(Name) \
70  IMP_HELPER_MACRO_PUSH_WARNINGS bool __eq__(const Name& o) const { \
71  return operator==(o); \
72  } \
73  bool __ne__(const Name& o) const { return operator!=(o); } \
74  bool __lt__(const Name& o) const { return operator<(o); } \
75  bool __gt__(const Name& o) const { return operator>(o); } \
76  bool __ge__(const Name& o) const { return operator>=(o); } \
77  bool __le__(const Name& o) const { return operator<=(o); } \
78  int __cmp__(const Name& o) const { return compare(o); } \
79  IMP_HELPER_MACRO_POP_WARNINGS IMP_REQUIRE_SEMICOLON_CLASS(comparisons)
80 
81 #define IMP_COMPARISONS(Name) \
82  IMP_SWIG_COMPARISONS(Name); \
83  IMP_HELPER_MACRO_PUSH_WARNINGS bool operator==(const Name& o) const { \
84  return (Name::compare(o) == 0); \
85  } \
86  bool operator!=(const Name& o) const { return (Name::compare(o) != 0); } \
87  bool operator<(const Name& o) const { return (Name::compare(o) < 0); } \
88  bool operator>(const Name& o) const { return (compare(o) > 0); } \
89  bool operator>=(const Name& o) const { return !(Name::compare(o) < 0); } \
90  bool operator<=(const Name& o) const { return !(Name::compare(o) > 0); } \
91  IMP_HELPER_MACRO_POP_WARNINGS template <class T> \
92  friend int compare(const T& a, const T& b)
93 
94 #define IMP_COMPARISONS_1(Name, field) \
95  IMP_SWIG_COMPARISONS(Name); \
96  IMP_HELPER_MACRO_PUSH_WARNINGS bool operator==(const Name& o) const { \
97  return (field == o.field); \
98  } \
99  bool operator!=(const Name& o) const { return (field != o.field); } \
100  bool operator<(const Name& o) const { return (field < o.field); } \
101  bool operator>(const Name& o) const { return (field > o.field); } \
102  bool operator>=(const Name& o) const { return (field >= o.field); } \
103  bool operator<=(const Name& o) const { return (field <= o.field); } \
104  int compare(const Name& o) const { \
105  if (operator<(o)) \
106  return -1; \
107  else if (operator>(o)) \
108  return 1; \
109  else \
110  return 0; \
111  } \
112  IMP_HELPER_MACRO_POP_WARNINGS
113 
114 #define IMP_COMPARISONS_2(Name, f0, f1) \
115  IMP_SWIG_COMPARISONS(Name); \
116  IMP_HELPER_MACRO_PUSH_WARNINGS bool operator==(const Name& o) const { \
117  return (f0 == o.f0 && f1 == o.f1); \
118  } \
119  bool operator!=(const Name& o) const { return (f0 != o.f0 || f1 != o.f1); } \
120  bool operator<(const Name& o) const { \
121  if (f0 < o.f0) \
122  return true; \
123  else if (f0 > o.f0) \
124  return false; \
125  else \
126  return f1 < o.f1; \
127  } \
128  bool operator>(const Name& o) const { \
129  if (f0 > o.f0) \
130  return true; \
131  else if (f0 < o.f0) \
132  return false; \
133  else \
134  return f1 > o.f1; \
135  } \
136  bool operator>=(const Name& o) const { return operator>(o) || operator==( \
137  o); } \
138  bool operator<=(const Name& o) const { return operator<(o) || operator==( \
139  o); } \
140  int compare(const Name& o) const { \
141  if (operator<(o)) \
142  return -1; \
143  else if (operator>(o)) \
144  return 1; \
145  else \
146  return 0; \
147  } \
148  IMP_HELPER_MACRO_POP_WARNINGS
149 
150 #define IMP_COMPARISONS_3(Name, f0, f1, f2) \
151  IMP_SWIG_COMPARISONS(Name); \
152  IMP_HELPER_MACRO_PUSH_WARNINGS bool operator==(const Name& o) const { \
153  return (f0 == o.f0 && f1 == o.f1 && f2 == o.f2); \
154  } \
155  bool operator!=(const Name& o) const { \
156  return (f0 != o.f0 || f1 != o.f1 || f2 != o.f2); \
157  } \
158  bool operator<(const Name& o) const { \
159  if (f0 < o.f0) \
160  return true; \
161  else if (f0 > o.f0) \
162  return false; \
163  if (f1 < o.f1) \
164  return true; \
165  else if (f1 > o.f1) \
166  return false; \
167  else \
168  return f2 < o.f2; \
169  } \
170  bool operator>(const Name& o) const { \
171  if (f0 > o.f0) \
172  return true; \
173  else if (f0 < o.f0) \
174  return false; \
175  if (f1 > o.f1) \
176  return true; \
177  else if (f1 < o.f1) \
178  return false; \
179  else \
180  return f2 > o.f2; \
181  } \
182  bool operator>=(const Name& o) const { return operator>(o) || operator==( \
183  o); } \
184  bool operator<=(const Name& o) const { return operator<(o) || operator==( \
185  o); } \
186  int compare(const Name& o) const { \
187  if (operator<(o)) \
188  return -1; \
189  else if (operator>(o)) \
190  return 1; \
191  else \
192  return 0; \
193  } \
194  IMP_HELPER_MACRO_POP_WARNINGS
195 #endif
196 
197 #ifdef SWIG
198 #define IMP_SAFE_BOOL(Name, expr)
199 #else
200 /** Implement the safe bool idiom in a class. The expression must
201  evaluate to a boolean.
202  */
203 #define IMP_SAFE_BOOL(Name, expr) \
204  private: \
205  typedef void (Name::*bool_type)() const; \
206  void this_type_does_not_support_comparisons() const {} \
207  \
208  public: \
209  operator bool_type() const { \
210  return (expr) ? &Name::this_type_does_not_support_comparisons : 0; \
211  }
212 
213 #endif
214 
215 /** Compare one value and return -1 or 1 as appropriate. If they are
216  equal, control returns to the current scope.
217 */
218 #define IMP_COMPARE_ONE(vara, varb) \
219  if (vara < varb) \
220  return -1; \
221  else if (varb < vara) \
222  return 1
223 
224 #endif /* IMPKERNEL_COMPARISON_MACROS_H */
Macros to control compiler warnings.