ModErn Text Analysis
META Enumerates Textual Applications
identifiers.h
Go to the documentation of this file.
1 
12 #ifndef META_NUMERIC_IDENTIFIER_H_
13 #define META_NUMERIC_IDENTIFIER_H_
14 
15 #include <functional> // for std::hash
16 
17 #include "meta/config.h"
18 #include "meta/hashing/hash.h"
19 #include "meta/util/comparable.h"
20 #include "meta/util/string_view.h"
21 
22 namespace meta
23 {
24 namespace util
25 {
26 
30 struct numeric
31 {
32 };
33 
37 template <class T>
38 struct is_numeric
39 {
40  const static constexpr bool value
41  = std::is_integral<T>::value || std::is_base_of<numeric, T>::value;
42 };
43 
48 template <class Tag, class T>
49 struct identifier : public comparable<identifier<Tag, T>>
50 {
51  using underlying_type = T;
52 
56  T id_;
57 
64  explicit constexpr identifier(const T& t) : id_{t}
65  {
66  // nothing
67  }
68 
72  identifier() = default;
73 
77  identifier(const identifier&) = default;
78 
82  identifier(identifier&&) = default;
83 
87  identifier& operator=(const identifier&) = default;
88 
92  identifier& operator=(identifier&&) = default;
93 
100  constexpr operator const T&() const
101  {
102  return id_;
103  }
104 
111  operator T&()
112  {
113  return id_;
114  }
115 
121  template <
122  typename U = T,
123  typename
124  = typename std::enable_if<std::is_same<U, std::string>::value>::type>
125  constexpr operator util::string_view() const
126  {
127  return id_;
128  }
129 
138  inline friend constexpr bool operator<(const identifier& lhs,
139  const identifier& rhs)
140  {
141  return static_cast<T>(lhs) < static_cast<T>(rhs);
142  }
143 
150  inline friend std::ostream& operator<<(std::ostream& stream,
151  const identifier& ident)
152  {
153  return stream << static_cast<T>(ident);
154  }
155 
162  inline friend std::istream& operator>>(std::istream& stream,
163  identifier& ident)
164  {
165  return stream >> ident.id_;
166  }
167 };
168 
169 template <class HashAlgorithm, class Tag, class T>
170 void hash_append(HashAlgorithm& h, const identifier<Tag, T>& id)
171 {
172  using hashing::hash_append;
173  hash_append(h, static_cast<const T&>(id));
174 }
175 
181 template <class Tag, class T>
182 struct numerical_identifier : public identifier<Tag, T>, numeric
183 {
187 
193  {
194  ++id_;
195  return *this;
196  }
197 
203  {
204  auto t = *this;
205  ++(*this);
206  return t;
207  }
208 
214  {
215  --id_;
216  return *this;
217  }
218 
224  {
225  auto t = *this;
226  --(*this);
227  return t;
228  }
229 
234  template <class U, class = typename std::
235  enable_if<std::is_convertible<U, T>::value>::type>
237  {
238  id_ += step;
239  return *this;
240  }
241 
246  template <class U, class = typename std::
247  enable_if<std::is_convertible<U, T>::value>::type>
249  {
250  id_ -= step;
251  return *this;
252  }
253 
260  friend inline numerical_identifier
262  {
263  lhs += static_cast<T>(rhs);
264  return lhs;
265  }
266 
273  friend inline numerical_identifier
275  {
276  lhs -= static_cast<T>(rhs);
277  return lhs;
278  }
279 };
280 }
281 }
282 
283 namespace std
284 {
285 
290 template <class Tag, class T>
291 struct hash<meta::util::identifier<Tag, T>>
292 {
298  size_t operator()(const meta::util::identifier<Tag, T>& to_hash) const
299  {
300  return hash<T>{}(static_cast<T>(to_hash));
301  }
302 };
303 
308 template <class Tag, class T>
309 struct hash<meta::util::numerical_identifier<Tag, T>>
310 {
316  size_t
318  {
319  return hash<T>{}(static_cast<T>(to_hash));
320  }
321 };
322 }
323 
324 #define MAKE_USER_DEFINED_LITERAL(ident_name, base_type, suffix) \
325  inline ident_name operator"" suffix(const char* str, std::size_t len) \
326  { \
327  return ident_name{base_type{str, len}}; \
328  }
329 
330 #define MAKE_USER_DEFINED_NUMERIC_LITERAL(ident_name, base_type, suffix) \
331  inline ident_name operator"" suffix(unsigned long long int val) \
332  { \
333  return ident_name{base_type(val)}; \
334  }
335 
336 #define MAKE_OPAQUE_IDENTIFIER(ident_name, base_type) \
337  struct ident_name##_tag \
338  { \
339  }; \
340  using ident_name = meta::util::identifier<ident_name##_tag, base_type>;
341 
342 #define MAKE_OPAQUE_NUMERIC_IDENTIFIER(ident_name, base_type) \
343  struct ident_name##_tag \
344  { \
345  }; \
346  using ident_name \
347  = meta::util::numerical_identifier<ident_name##_tag, base_type>;
348 
349 #define MAKE_IDENTIFIER(ident_name, base_type) \
350  MAKE_OPAQUE_IDENTIFIER(ident_name, base_type)
351 
352 #define MAKE_NUMERIC_IDENTIFIER(ident_name, base_type) \
353  MAKE_OPAQUE_NUMERIC_IDENTIFIER(ident_name, base_type)
354 
355 #define MAKE_IDENTIFIER_UDL(ident_name, base_type, suffix) \
356  MAKE_OPAQUE_IDENTIFIER(ident_name, base_type) \
357  MAKE_USER_DEFINED_LITERAL(ident_name, base_type, suffix)
358 
359 #define MAKE_NUMERIC_IDENTIFIER_UDL(ident_name, base_type, suffix) \
360  MAKE_OPAQUE_NUMERIC_IDENTIFIER(ident_name, base_type) \
361  MAKE_USER_DEFINED_NUMERIC_LITERAL(ident_name, base_type, suffix)
362 
363 #endif
A CRTP template base that adds numeric functionality to the identifier type.
Definition: identifiers.h:182
numerical_identifier operator--(int)
Postfix-decrement.
Definition: identifiers.h:223
numerical_identifier operator++(int)
Postifx-increment.
Definition: identifiers.h:202
friend numerical_identifier operator+(numerical_identifier lhs, const numerical_identifier &rhs)
Definition: identifiers.h:261
STL namespace.
friend constexpr bool operator<(const identifier &lhs, const identifier &rhs)
identifiers are comparable by their base types.
Definition: identifiers.h:138
Type trait for numeric.
Definition: identifiers.h:38
Empty helper class to denote that something is numeric.
Definition: identifiers.h:30
A non-owning reference to a string.
Definition: string_view.h:51
friend std::istream & operator>>(std::istream &stream, identifier &ident)
identifiers may be read from input streams.
Definition: identifiers.h:162
size_t operator()(const meta::util::numerical_identifier< Tag, T > &to_hash) const
Definition: identifiers.h:317
friend std::ostream & operator<<(std::ostream &stream, const identifier &ident)
identifiers may be printed to output streams.
Definition: identifiers.h:150
friend numerical_identifier operator-(numerical_identifier lhs, const numerical_identifier &rhs)
Definition: identifiers.h:274
The ModErn Text Analysis toolkit is a suite of natural language processing, classification, information retrieval, data mining, and other applications of text processing.
Definition: analyzer.h:25
constexpr identifier(const T &t)
identifiers must be explicitly constructed from their base type—they cannot be implicitly converted ...
Definition: identifiers.h:64
numerical_identifier & operator--()
Prefix-decrement.
Definition: identifiers.h:213
Base template that denotes an identifier.
Definition: identifiers.h:49
T id_
The underlying id for the identifier.
Definition: identifiers.h:56
numerical_identifier & operator++()
Prefix-increment.
Definition: identifiers.h:192
numerical_identifier & operator-=(const T &step)
Definition: identifiers.h:248
size_t operator()(const meta::util::identifier< Tag, T > &to_hash) const
Definition: identifiers.h:298
numerical_identifier & operator+=(const T &step)
Definition: identifiers.h:236
A CRTP base class that allows for inheritance of all comparator operators given that the derived clas...
Definition: comparable.h:28