CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Equal.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <typeinfo>
4 #include <type_traits>
5 
6 #include <algorithm>
7 
8 #include <string>
9 #include <bitset>
10 #include <utility>
11 #include <tuple>
12 #include <memory>
13 #include <array>
14 #include <vector>
15 #include <deque>
16 #include <forward_list>
17 #include <list>
18 #include <set>
19 #include <unordered_set>
20 #include <map>
21 #include <unordered_map>
22 
23 #include <cstddef>
24 #include <cmath>
25 
26 #include <boost/shared_ptr.hpp>
27 
29 
30 namespace cond {
31 namespace serialization {
32 
33 template <typename T>
34 bool equal(const T & first, const T & second)
35 {
36  // This function takes advantage of template argument deduction,
37  // making it easier to use than the access<T> template.
38 
39  // It is also called by the access<T>::equal_() methods themselves
40  // if they need to compare objects. This means all comparisons
41  // pass by here.
42 
43  // Therefore, we could easily first check here whether the address of
44  // the objects is the same or add debugging code. In our use case,
45  // however, most of the objects will have different addresses.
46  return access<T>::equal_(first, second);
47 }
48 
49 template <typename T>
50 struct access<T, typename std::enable_if<std::is_integral<T>::value or std::is_enum<T>::value>::type>
51 {
52  static bool equal_(const T first, const T second)
53  {
54  return first == second;
55  }
56 };
57 
58 template <typename T>
59 struct access<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
60 {
61  static bool equal_(const T first, const T second)
62  {
63  // TODO: we consider all NaNs to be equal -- should we even allow to serialize them?
64  if (std::isnan(first) or std::isnan(second))
65  return std::isnan(first) and std::isnan(second);
66 
67  if (std::isinf(first) or std::isinf(second))
68  return std::isinf(first) and std::isinf(second) and std::signbit(first) == std::signbit(second);
69 
70  // TODO: consider expected precision for cross-platform serialization
71  return first == second;
72  }
73 };
74 
75 template <>
76 struct access<std::string>
77 {
78  static bool equal_(const std::string & first, const std::string & second)
79  {
80  return first == second;
81  }
82 };
83 
84 template <std::size_t N>
85 struct access<std::bitset<N>>
86 {
87  static bool equal_(const std::bitset<N> & first, const std::bitset<N> & second)
88  {
89  return first == second;
90  }
91 };
92 
93 template <typename T, typename U>
94 struct access<std::pair<T, U>>
95 {
96  static bool equal_(const std::pair<T, U> & first, const std::pair<T, U> & second)
97  {
98  return equal(first.first, second.first) and equal(first.second, second.second);
99  }
100 };
101 
102 template <std::size_t N, typename... Ts>
104 {
105  static bool equal_(const std::tuple<Ts...> & first, const std::tuple<Ts...> & second)
106  {
107  if (not equal(std::get<N - 1>(first), std::get<N - 1>(second)))
108  return false;
109 
110  return equal_tuple<N - 1, Ts...>::equal_(first, second);
111  }
112 };
113 
114 template <typename... Ts>
115 struct equal_tuple<0, Ts...>
116 {
117  static bool equal_(const std::tuple<Ts...> & first, const std::tuple<Ts...> & second)
118  {
119  return true;
120  }
121 };
122 
123 template <typename... Ts>
124 struct access<std::tuple<Ts...>>
125 {
126  static bool equal_(const std::tuple<Ts...> & first, const std::tuple<Ts...> & second)
127  {
128  return equal_tuple<sizeof...(Ts), Ts...>::equal_(first, second);
129  }
130 };
131 
132 template <typename T>
133 struct access<T, typename std::enable_if<std::is_pointer<T>::value>::type>
134 {
135  static bool equal_(const T first, const T second)
136  {
137  if (first == nullptr or second == nullptr)
138  return first == second;
139 
140  // Compare the addresses first -- even if equal() does not
141  // do it for all types, if we are serializing pointers we may
142  // have some use case of containers of pointers to a small
143  // set of real objects.
144  return first == second or equal(*first, *second);
145  }
146 };
147 
148 #define equal_pointer(TYPE) \
149 template <typename T> \
150 struct access<TYPE<T>> \
151 { \
152  static bool equal_(const TYPE<T> & first, const TYPE<T> & second) \
153  { \
154  return equal(first.get(), second.get()); \
155  } \
156 };
157 
158 equal_pointer(std::unique_ptr);
159 equal_pointer(std::shared_ptr);
160 equal_pointer(boost::shared_ptr);
161 #undef equal_pointer
162 
163 template <typename T, std::size_t N>
164 struct access<T[N]>
165 {
166  static bool equal_(const T (&first)[N], const T (&second)[N])
167  {
168  for (std::size_t i = 0; i < N; ++i)
169  if (not equal(first[i], second[i]))
170  return false;
171  return true;
172  }
173 };
174 
175 template <typename T, std::size_t N>
176 struct access<std::array<T, N>>
177 {
178  static bool equal_(const std::array<T, N> & first, const std::array<T, N> & second)
179  {
180  for (std::size_t i = 0; i < N; ++i)
181  if (not equal(first[i], second[i]))
182  return false;
183  return true;
184  }
185 };
186 
187 #define equal_sequence(TYPE) \
188 template <typename T> \
189 struct access<TYPE<T>> \
190 { \
191  static bool equal_(const TYPE<T> & first, const TYPE<T> & second) \
192  { \
193  return first.size() == second.size() && std::equal(first.cbegin(), first.cend(), second.cbegin(), \
194  [](decltype(*first.cbegin()) a, decltype(a) b) -> bool { \
195  return equal(a, b); \
196  } \
197  ); \
198  } \
199 };
200 
201 equal_sequence(std::vector);
202 equal_sequence(std::deque);
204 equal_sequence(std::set); // ordered
205 equal_sequence(std::multiset); // ordered
206 #undef equal_sequence
207 
208 // forward_list is a sequence, but does not provide size() and we are not yet
209 // in C++14 so we cannot use the 4 iterators version of std::equal()
210 template <typename T>
211 struct access<std::forward_list<T>>
212 {
213  static bool equal_(const std::forward_list<T> & first, const std::forward_list<T> & second)
214  {
215  auto first_it = first.cbegin();
216  auto second_it = second.cbegin();
217 
218  while (first_it != first.cend() and second_it != second.cend()) {
219  if (not equal(*first_it, *second_it))
220  return false;
221  first_it++;
222  second_it++;
223  }
224 
225  return first_it == first.cend() and second_it == second.cend();
226  }
227 };
228 
229 // map is ordered too, we can iterate like a sequence
230 #define equal_mapping(TYPE) \
231 template <typename T, typename U> \
232 struct access<TYPE<T, U>> \
233 { \
234  static bool equal_(const TYPE<T, U> & first, const TYPE<T, U> & second) \
235  { \
236  return first.size() == second.size() && std::equal(first.cbegin(), first.cend(), second.cbegin(), \
237  [](decltype(*first.cbegin()) a, decltype(a) b) -> bool { \
238  return equal(a, b); \
239  } \
240  ); \
241  } \
242 };
243 
245 #undef equal_mapping
246 
247 #define equal_unorderedmapping(TYPE) \
248 template <typename T, typename U> \
249 struct access<TYPE<T, U>> \
250 { \
251  static bool equal_(const TYPE<T, U> & first, const TYPE<T, U> & second) \
252  { \
253  if (first.size() != second.size()) \
254  return false; \
255  \
256  auto first_it = first.cbegin(); \
257  while (first_it != first.cend()) { \
258  auto second_it = second.find(first_it->first); \
259  if (second_it == second.cend()) \
260  return false; \
261  if (not equal(first_it->second, second_it->second)) \
262  return false; \
263  first_it++; \
264  } \
265  return true; \
266  } \
267 };
268 
269 equal_unorderedmapping(std::unordered_map);
270 #undef equal_unorderedmapping
271 
272 }
273 }
274 
static bool equal_(const std::tuple< Ts...> &first, const std::tuple< Ts...> &second)
Definition: Equal.h:105
type
Definition: HCALResponse.h:21
int i
Definition: DBlmapReader.cc:9
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
bool isinf(T value)
Definition: CommonUtils.h:7
static bool equal_(const std::tuple< Ts...> &first, const std::tuple< Ts...> &second)
Definition: Equal.h:126
#define equal_sequence(TYPE)
Definition: Equal.h:187
bool equal(const T &first, const T &second)
Definition: Equal.h:34
U second(std::pair< T, U > const &p)
static bool equal_(const std::tuple< Ts...> &first, const std::tuple< Ts...> &second)
Definition: Equal.h:117
static bool equal_(const std::bitset< N > &first, const std::bitset< N > &second)
Definition: Equal.h:87
static bool equal_(const T(&first)[N], const T(&second)[N])
Definition: Equal.h:166
bool isnan(float x)
Definition: math.h:13
static bool equal_(const std::array< T, N > &first, const std::array< T, N > &second)
Definition: Equal.h:178
#define equal_mapping(TYPE)
Definition: Equal.h:230
static bool equal_(const std::string &first, const std::string &second)
Definition: Equal.h:78
#define N
Definition: blowfish.cc:9
static bool equal_(const std::forward_list< T > &first, const std::forward_list< T > &second)
Definition: Equal.h:213
#define equal_pointer(TYPE)
Definition: Equal.h:148
static bool equal_(const std::pair< T, U > &first, const std::pair< T, U > &second)
Definition: Equal.h:96
long double T
#define equal_unorderedmapping(TYPE)
Definition: Equal.h:247
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run