CMS 3D CMS Logo

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 
27 
28 namespace cond {
29  namespace serialization {
30 
31  template <typename T>
32  bool equal(const T& first, const T& second) {
33  // This function takes advantage of template argument deduction,
34  // making it easier to use than the access<T> template.
35 
36  // It is also called by the access<T>::equal_() methods themselves
37  // if they need to compare objects. This means all comparisons
38  // pass by here.
39 
40  // Therefore, we could easily first check here whether the address of
41  // the objects is the same or add debugging code. In our use case,
42  // however, most of the objects will have different addresses.
44  }
45 
46  template <typename T>
47  struct access<T, typename std::enable_if<std::is_integral<T>::value or std::is_enum<T>::value>::type> {
48  static bool equal_(const T first, const T second) { return first == second; }
49  };
50 
51  template <typename T>
52  struct access<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
53  static bool equal_(const T first, const T second) {
54  // TODO: we consider all NaNs to be equal -- should we even allow to serialize them?
56  return std::isnan(first) and std::isnan(second);
57 
58  if (std::isinf(first) or std::isinf(second))
59  return std::isinf(first) and std::isinf(second) and std::signbit(first) == std::signbit(second);
60 
61  // TODO: consider expected precision for cross-platform serialization
62  return first == second;
63  }
64  };
65 
66  template <>
67  struct access<std::string> {
68  static bool equal_(const std::string& first, const std::string& second) { return first == second; }
69  };
70 
71  template <std::size_t N>
72  struct access<std::bitset<N>> {
73  static bool equal_(const std::bitset<N>& first, const std::bitset<N>& second) { return first == second; }
74  };
75 
76  template <typename T, typename U>
77  struct access<std::pair<T, U>> {
78  static bool equal_(const std::pair<T, U>& first, const std::pair<T, U>& second) {
79  return equal(first.first, second.first) and equal(first.second, second.second);
80  }
81  };
82 
83  template <std::size_t N, typename... Ts>
84  struct equal_tuple {
85  static bool equal_(const std::tuple<Ts...>& first, const std::tuple<Ts...>& second) {
86  if (not equal(std::get<N - 1>(first), std::get<N - 1>(second)))
87  return false;
88 
90  }
91  };
92 
93  template <typename... Ts>
94  struct equal_tuple<0, Ts...> {
95  static bool equal_(const std::tuple<Ts...>& first, const std::tuple<Ts...>& second) { return true; }
96  };
97 
98  template <typename... Ts>
99  struct access<std::tuple<Ts...>> {
100  static bool equal_(const std::tuple<Ts...>& first, const std::tuple<Ts...>& second) {
101  return equal_tuple<sizeof...(Ts), Ts...>::equal_(first, second);
102  }
103  };
104 
105  template <typename T>
106  struct access<T, typename std::enable_if<std::is_pointer<T>::value>::type> {
107  static bool equal_(const T first, const T second) {
108  if (first == nullptr or second == nullptr)
109  return first == second;
110 
111  // Compare the addresses first -- even if equal() does not
112  // do it for all types, if we are serializing pointers we may
113  // have some use case of containers of pointers to a small
114  // set of real objects.
115  return first == second or equal(*first, *second);
116  }
117  };
118 
119 #define equal_pointer(TYPE) \
120  template <typename T> \
121  struct access<TYPE<T>> { \
122  static bool equal_(const TYPE<T>& first, const TYPE<T>& second) { return equal(first.get(), second.get()); } \
123  };
124 
126  equal_pointer(std::shared_ptr);
127 #undef equal_pointer
128 
129  template <typename T, std::size_t N>
130  struct access<T[N]> {
131  static bool equal_(const T (&first)[N], const T (&second)[N]) {
132  for (std::size_t i = 0; i < N; ++i)
133  if (not equal(first[i], second[i]))
134  return false;
135  return true;
136  }
137  };
138 
139  template <typename T, std::size_t N>
140  struct access<std::array<T, N>> {
141  static bool equal_(const std::array<T, N>& first, const std::array<T, N>& second) {
142  for (std::size_t i = 0; i < N; ++i)
143  if (not equal(first[i], second[i]))
144  return false;
145  return true;
146  }
147  };
148 
149 #define equal_sequence(TYPE) \
150  template <typename T> \
151  struct access<TYPE<T>> { \
152  static bool equal_(const TYPE<T>& first, const TYPE<T>& second) { \
153  return first.size() == second.size() && \
154  std::equal(first.cbegin(), \
155  first.cend(), \
156  second.cbegin(), \
157  [](decltype(*first.cbegin()) a, decltype(*first.cbegin()) b) -> bool { return equal(a, b); }); \
158  } \
159  };
160 
162  equal_sequence(std::deque);
163  equal_sequence(std::list);
164  equal_sequence(std::set); // ordered
165  equal_sequence(std::multiset); // ordered
166 #undef equal_sequence
167 
168  // forward_list is a sequence, but does not provide size() and we are not yet
169  // in C++14 so we cannot use the 4 iterators version of std::equal()
170  template <typename T>
171  struct access<std::forward_list<T>> {
172  static bool equal_(const std::forward_list<T>& first, const std::forward_list<T>& second) {
173  auto first_it = first.cbegin();
174  auto second_it = second.cbegin();
175 
176  while (first_it != first.cend() and second_it != second.cend()) {
177  if (not equal(*first_it, *second_it))
178  return false;
179  first_it++;
180  second_it++;
181  }
182 
183  return first_it == first.cend() and second_it == second.cend();
184  }
185  };
186 
187 // map is ordered too, we can iterate like a sequence
188 #define equal_mapping(TYPE) \
189  template <typename T, typename U> \
190  struct access<TYPE<T, U>> { \
191  static bool equal_(const TYPE<T, U>& first, const TYPE<T, U>& second) { \
192  return first.size() == second.size() && \
193  std::equal(first.cbegin(), \
194  first.cend(), \
195  second.cbegin(), \
196  [](decltype(*first.cbegin()) a, decltype(*first.cbegin()) b) -> bool { return equal(a, b); }); \
197  } \
198  };
199 
201 #undef equal_mapping
202 
203 #define equal_unorderedmapping(TYPE) \
204  template <typename T, typename U> \
205  struct access<TYPE<T, U>> { \
206  static bool equal_(const TYPE<T, U>& first, const TYPE<T, U>& second) { \
207  if (first.size() != second.size()) \
208  return false; \
209  \
210  auto first_it = first.cbegin(); \
211  while (first_it != first.cend()) { \
212  auto second_it = second.find(first_it->first); \
213  if (second_it == second.cend()) \
214  return false; \
215  if (not equal(first_it->second, second_it->second)) \
216  return false; \
217  first_it++; \
218  } \
219  return true; \
220  } \
221  };
222 
223  equal_unorderedmapping(std::unordered_map);
224 #undef equal_unorderedmapping
225 
226  } // namespace serialization
227 } // namespace cond
def isnan(num)
static bool equal_(const std::tuple< Ts... > &first, const std::tuple< Ts... > &second)
Definition: Equal.h:100
static bool equal_(const std::tuple< Ts... > &first, const std::tuple< Ts... > &second)
Definition: Equal.h:85
#define equal_sequence(TYPE)
Definition: Equal.h:149
std::unique_ptr< T, impl::DeviceDeleter > unique_ptr
bool equal(const T &first, const T &second)
Definition: Equal.h:32
U second(std::pair< T, U > const &p)
static bool equal_(const std::bitset< N > &first, const std::bitset< N > &second)
Definition: Equal.h:73
static bool equal_(const T(&first)[N], const T(&second)[N])
Definition: Equal.h:131
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::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
static bool equal_(const std::array< T, N > &first, const std::array< T, N > &second)
Definition: Equal.h:141
#define equal_mapping(TYPE)
Definition: Equal.h:188
static bool equal_(const std::string &first, const std::string &second)
Definition: Equal.h:68
#define N
Definition: blowfish.cc:9
static bool equal_(const std::tuple< Ts... > &first, const std::tuple< Ts... > &second)
Definition: Equal.h:95
static bool equal_(const std::forward_list< T > &first, const std::forward_list< T > &second)
Definition: Equal.h:172
#define equal_pointer(TYPE)
Definition: Equal.h:119
static bool equal_(const std::pair< T, U > &first, const std::pair< T, U > &second)
Definition: Equal.h:78
long double T
#define equal_unorderedmapping(TYPE)
Definition: Equal.h:203