HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
enum.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_ENUM_H
8 #define PXR_BASE_TF_ENUM_H
9 
10 /// \file tf/enum.h
11 /// \ingroup group_tf_RuntimeTyping
12 
13 #include "pxr/pxr.h"
14 #include "pxr/base/arch/defines.h"
15 #include "pxr/base/arch/demangle.h"
16 #include "pxr/base/tf/hash.h"
19 #include "pxr/base/tf/api.h"
20 
21 
22 #include <iosfwd>
23 #include <string>
24 #include <typeinfo>
25 #include <type_traits>
26 #include <vector>
27 
29 
30 /// \class TfEnum
31 /// \ingroup group_tf_RuntimeTyping
32 ///
33 /// An enum class that records both enum type and enum value.
34 ///
35 /// \section cppcode_runtimeTyping Run-Time Typing
36 ///
37 /// A \c TfEnum can hold an enum variable of any enum type, while still
38 /// being able to distinguish between various enum types.
39 /// Here is an example:
40 ///
41 /// \code
42 /// enum Monsters { SULLEY = 0, MIKE, ROZ };
43 /// enum Fish { NEMO = 0, FATHER, DORY };
44 ///
45 /// TfEnum t1 = MIKE,
46 /// t2 = NEMO;
47 ///
48 /// t1 == MIKE; // yields true
49 /// t2 == NEMO; // yields true
50 /// t1 == t2; // yields false
51 /// t1 == SULLEY; // yields false
52 ///
53 /// t1.IsA<Monsters>(); // yields true
54 /// t1.IsA<Fish>(); // yields false
55 /// \endcode
56 ///
57 /// Even though \c NEMO and \c SULLEY both are represented with integral
58 /// value zero, \c t1 and \c t2 compare false. A \c TfEnum can be passed
59 /// by value, assigned, etc. just like a regular \c Enum variable.
60 /// A \c TfEnum can also hold a plain integer, which will compare false against
61 /// any other enum variable.
62 ///
63 /// \section cppcode_enumvals Associating Names with Enumerated Values
64 ///
65 /// The \c TfEnum class can also be used to represent enumerated values
66 /// as strings. This can be useful for storing enum values in files for
67 /// later retrieval.
68 ///
69 /// Use the \c TF_ADD_ENUM_NAME() macro to set up and enable strings
70 /// for the values of an enum. Once this is done, several static
71 /// \c TfEnum methods may be used to look up names corresponding to enum
72 /// values and vice-versa.
73 ///
74 /// For example, see \c TfRegistryManager to understand the use of
75 /// the \c TF_REGISTRY_FUNCTION() macro below:
76 ///
77 /// \section cppcode_enumRegMacro Enum Registration Macro
78 ///
79 /// \code
80 /// // header file
81 /// // Declare an enumerated type with some values
82 /// enum Season {
83 /// SPRING,
84 /// SUMMER = 3, // It's ok to have initializers
85 /// AUTUMN,
86 /// WINTER
87 /// };
88 ///
89 /// // source file
90 /// #include "pxr/base/tf/registryManager.h"
91 /// TF_REGISTRY_FUNCTION(TfEnum) {
92 /// // Register the names for the values:
93 /// TF_ADD_ENUM_NAME(SPRING);
94 /// TF_ADD_ENUM_NAME(SUMMER);
95 /// TF_ADD_ENUM_NAME(AUTUMN);
96 /// TF_ADD_ENUM_NAME(WINTER);
97 /// }
98 ///
99 /// // another source file:
100 ///
101 /// // Look up the name for a value:
102 /// string name1 = TfEnum::GetName(SUMMER); // Returns "SUMMER"
103 /// string name2 = TfEnum::GetFullName(SUMMER); // Returns "Season::SUMMER"
104 ///
105 /// // Look up the value for a name:
106 /// bool found;
107 /// Season s1 = TfEnum::GetValueFromName<Season>("AUTUMN", &found);
108 /// // Returns 4, sets found to true
109 /// Season s2 = TfEnum::GetValueFromName<Season>("MONDAY", &found);
110 /// // Returns -1, sets found to false
111 ///
112 /// // Look up a fully-qualified name. Since this is not a templated
113 /// // function, it has to return a generic value type, so we use
114 /// // TfEnum.
115 /// TfEnum s3 = TfEnum::GetValueFromFullName("Season::WINTER", &found);
116 /// // Returns 5, sets found to \c true
117 /// \endcode
118 ///
119 class TfEnum
120 {
121 public:
122  /// Default constructor assigns integer value zero.
124  : _typeInfo(&typeid(int)), _value(0)
125  {
126  }
127 
128  /// Initializes value to enum variable \c value of enum type \c T.
129  template <class T>
132  : _typeInfo(&typeid(T)), _value(int(value))
133  {
134  }
135 
136  /// Initializes value to integral value \p value with enum type \c ti.
137  ///
138  /// \warning This is only for use in extreme circumstances; there is no
139  /// way for an implementation to guarantee that \p ti is really an enum
140  /// type, and/or that \p value is a valid value for that enum type.
141  TfEnum(const std::type_info& ti, int value)
142  : _typeInfo(&ti), _value(value)
143  {
144  }
145 
146  /// True if \c *this and \c t have both the same type and value.
147  bool operator==(const TfEnum& t) const {
148  return t._value == _value &&
149  TfSafeTypeCompare(*t._typeInfo, *_typeInfo);
150  }
151 
152  /// Inequality operator
153  /// \sa TfEnum::operator==(const TfEnum&)
154  bool operator!=(const TfEnum& t) const {
155  return !(*this == t);
156  }
157 
158  /// Less than comparison. Enum values belonging to the same type are
159  /// ordered according to their numeric value. Enum values belonging to
160  /// different types are ordered in a consistent but arbitrary way which
161  /// may vary between program runs.
162  bool operator<(const TfEnum& t) const {
163  return _typeInfo->before(*t._typeInfo) ||
164  (!t._typeInfo->before(*_typeInfo) && _value < t._value);
165  }
166 
167  /// Less than or equal operator
168  /// \sa TfEnum::operator<(const TfEnum&)
169  bool operator<=(const TfEnum& t) const {
170  return !(t < *this);
171  }
172 
173  /// Greater than operator
174  /// \sa TfEnum::operator<(const TfEnum&)
175  bool operator>(const TfEnum& t) const {
176  return t < *this;
177  }
178 
179  /// Greater than or equal operator
180  /// \sa TfEnum::operator<(const TfEnum&)
181  bool operator>=(const TfEnum& t) const {
182  return !(*this < t);
183  }
184 
185  /// True if \c *this has been assigned with \c value.
186  template <class T>
188  operator==(T value) const {
189  return int(value) == _value && IsA<T>();
190  }
191 
192  /// False if \c *this has been assigned with \c value.
193  template <class T>
195  operator!=(T value) const {
196  return int(value) != _value || !IsA<T>();
197  }
198 
199  /// Compare a literal enum value \a val of enum type \a T with TfEnum \a e.
200  template <class T>
202  operator==(T val, TfEnum const &e) {
203  return e == val;
204  }
205 
206  /// Compare a literal enum value \a val of enum type \a T with TfEnum \a e.
207  template <class T>
209  operator!=(T val, TfEnum const &e) {
210  return e != val;
211  }
212 
213  /// True if \c *this has been assigned any enumerated value of type \c T.
214  template <class T>
215  bool IsA() const {
216  return TfSafeTypeCompare(*_typeInfo, typeid(T));
217  }
218 
219  /// True if \c *this has been assigned any enumerated value of type
220  /// \c T with \c typeid(T)==t.
221  bool IsA(const std::type_info& t) const {
222  return TfSafeTypeCompare(*_typeInfo, t);
223  }
224 
225  /// Returns the type of the enum value, as an \c std::type_info.
226  const std::type_info& GetType() const {
227  return *_typeInfo;
228  }
229 
230  /// Returns the integral value of the enum value.
231  const int& GetValueAsInt() const {
232  return _value;
233  }
234 
235  /// Returns the enum value for the enum type \c T.
236  ///
237  /// \warning This function can cause your program to abort if not used
238  /// properly.
239  ///
240  /// If it is possible that the enum value is not of type \c T, first use
241  /// \c IsA() to test whether the enum value is of type \c T before calling
242  /// \c GetValue<T>().
243  ///
244  /// Note that if \c IsA<T>() succeeds, then \c GetValue<T>() will also
245  /// succeed.
246  template <typename T>
247  T GetValue() const {
248  if (!IsA<T>())
249  _FatalGetValueError(typeid(T));
250 
251  return T(_value);
252  }
253 
254  /// Conversion operator for enum and integral types only.
255  template <typename T,
256  typename = typename std::enable_if<
259  >
260  operator T() const
261  {
262  return T(_value);
263  }
264 
265  /// \name Retrieving Corresponding Names and Enumerated Values
266  ///
267  /// The methods in this group can be used to retrieve corresponding names
268  /// and values. The correspondences are set up with the
269  /// \c TF_ADD_ENUM_NAME() macro.
270  ///
271  ///@{
272 
273  /// Returns the name associated with an enumerated value.
274  ///
275  /// If there is no such name registered, an empty string is returned.
276  TF_API static std::string GetName(TfEnum val);
277 
278  /// Returns the fully-qualified name for an enumerated value.
279  ///
280  /// This returns a fully-qualified enumerated value name (e.g.,
281  /// \c "Season::WINTER") associated with the given value. If there is no
282  /// such name registered, an empty string is returned.
283  TF_API static std::string GetFullName(TfEnum val);
284 
285  /// Returns the display name for an enumerated value.
286  ///
287  /// This returns a user interface-suitable string for the given enumerated
288  /// value.
289  TF_API static std::string GetDisplayName(TfEnum val);
290 
291  /// Returns a vector of all the names associated with an enum type.
292  ///
293  /// This returns a vector of all the names associated with the enum that
294  /// contains the type \p val. The names are not fully qualified. For
295  /// example, \c TfEnum::GetAllNames(WINTER) would return a vector
296  /// containing "SPRING", "SUMMER", "AUTUMN", and "WINTER".
297  ///
298  /// If there are no such names registered, an empty vector is returned.
299  static std::vector<std::string> GetAllNames(TfEnum val) {
300  return GetAllNames(val.GetType());
301  }
302 
303  /// \overload
304  TF_API static std::vector<std::string> GetAllNames(const std::type_info &ti);
305 
306  /// Returns a vector of all the names associated with an enum type.
307  ///
308  /// This returns a vector of all the names associated with the enum
309  /// type \c T. The names are not fully qualified. For
310  /// example, \c TfEnum::GetAllNames<Season>() would return a vector
311  /// containing "SPRING", "SUMMER", "AUTUMN", and "WINTER".
312  ///
313  /// If there are no such names registered, an empty vector is returned.
314  template <class T>
315  static std::vector<std::string> GetAllNames() {
316  return GetAllNames(typeid(T));
317  }
318 
319  /// Returns the typeid for a given enum type name.
320  ///
321  /// This returns a pointer to the type_info associated with the enum that
322  /// has the type name \c typeName. If no such enum is registered, returns
323  /// NULL.
324  TF_API
325  static const std::type_info *GetTypeFromName(const std::string& typeName);
326 
327  /// Returns the enumerated value for a name.
328  ///
329  /// If there is no such name registered, this returns -1. Since -1 can
330  /// sometimes be a valid value, the \p foundIt flag pointer, if not \c
331  /// NULL, is set to \c true if the name was found and \c false otherwise.
332  template <class T>
333  static T GetValueFromName(const std::string &name, bool *foundIt = NULL) {
334  TfEnum e = GetValueFromName(typeid(T), name, foundIt);
335  return T(e.GetValueAsInt());
336  }
337 
338  /// Returns the enumerated value for a name.
339  ///
340  /// This is a template-independent version of \c GetValueFromName().
341  TF_API
342  static TfEnum GetValueFromName(const std::type_info& ti,
343  const std::string &name,
344  bool *foundIt = NULL);
345 
346  /// Returns the enumerated value for a fully-qualified name.
347  ///
348  /// This takes a fully-qualified enumerated value name (e.g.,
349  /// \c "Season::WINTER") and returns the associated value. If there is
350  /// no such name, this returns -1. Since -1 can sometimes be a
351  /// valid value, the \p foundIt flag pointer, if not \c NULL, is
352  /// set to \c true if the name was found and \c false
353  /// otherwise. Also, since this is not a templated function, it has
354  /// to return a generic value type, so we use \c TfEnum.
355  TF_API
356  static TfEnum GetValueFromFullName(const std::string &fullname,
357  bool *foundIt = NULL);
358 
359  /// Returns true if \p typeName is a known enum type.
360  ///
361  /// If any enum whose demangled type name is \p typeName has been
362  /// added via \c TF_ADD_ENUM_NAME(), this function returns true.
363  TF_API
364  static bool IsKnownEnumType(const std::string& typeName);
365 
366  ///@}
367 
368  /// Associates a name with an enumerated value.
369  ///
370  /// \warning This method is called by the \c TF_ADD_ENUM_NAME() macro, and
371  /// should NOT be called directly. Instead, call AddName(), which does
372  /// exactly the same thing.
373  TF_API
374  static void _AddName(TfEnum val, char const *valName,
375  char const *displayName);
376 
377  // Helper for TF_ADD_ENUM_NAME() dealing with empty vs nonempty __VA_ARGS__
378  static char const *
379  _NameIdent(char const *str = nullptr) { return str; }
380 
381  /// Associates a name with an enumerated value.
382  /// \see _AddName().
383  static void AddName(TfEnum val, const std::string &valName,
384  const std::string &displayName="")
385  {
386  _AddName(val, valName.c_str(), displayName.c_str());
387  }
388 
389  template <typename T>
391  TfEnum e;
392  e._typeInfo = &typeid(T);
393  e._value = int(value);
394  return e;
395  }
396 
397 private:
398  // Internal constructor for int values.
399  explicit TfEnum(int value)
400  : _typeInfo(&typeid(int)), _value(value)
401  {
402  }
403 
404  // Internal constructor for size_t values.
405  explicit TfEnum(size_t value)
406  : _typeInfo(&typeid(size_t)), _value(static_cast<int>(value))
407  {
408  }
409 
410  TF_API
411  void _FatalGetValueError(std::type_info const& typeInfo) const;
412 
413  const std::type_info* _typeInfo;
414  int _value;
415 };
416 
417 // TfHash support. Make the enum parameter be a deduced template type but
418 // enable the overload only for TfEnum. This disables implicit conversion from
419 // ordinary enum types to TfEnum.
420 template <class HashState, class Enum>
422 TfHashAppend(HashState &h, Enum const &e)
423 {
424  h.Append(TfHashAsCStr(e.GetType().name()));
425  h.Append(e.GetValueAsInt());
426 }
427 
428 /// Output a TfEnum value.
429 /// \ingroup group_tf_DebuggingOutput
430 TF_API std::ostream& operator<<(std::ostream& out, const TfEnum & e);
431 
432 /// Macro used to associate a name with an enumerated value.
433 ///
434 /// \c TF_ADD_ENUM_NAME() registers a name for an enumerated value so that the
435 /// association can be accessed in calls to \c TfEnum::GetValueFromName(),
436 /// \c TfEnum::GetValueFromFullName(), \c TfEnum::GetName(), and
437 /// \c TfEnum::GetFullName(). It's first argument, \p VAL, is the symbolic
438 /// name of the enumerated value or a \c TfEnum instance constructed from it.
439 /// The name defined for the value is created by putting double quotes around
440 /// the \p VAL argument.
441 ///
442 /// An optional second argument, \p DISPLAY, is a name to be used for display
443 /// purposes (i.e. in a user interface). The display name can contain
444 /// characters like spaces and punctuation, and does not need to be a unique
445 /// string. If this argument is not specified, the display name will be
446 /// derived from \p VAL.
447 ///
448 /// Only the names for which \c TF_ADD_ENUM_NAME() is called will be
449 /// accessible with the name/value methods; you can hide values from this
450 /// mechanism by not adding them.
451 ///
452 /// Please note that the best way to call \c TF_ADD_ENUM_NAME() is using the
453 /// \c TfRegistryManager macro \c TF_REGISTRY_FUNCTION().
454 ///
455 /// \ingroup group_tf_RuntimeTyping
456 /// \hideinitializer
457 #define TF_ADD_ENUM_NAME(VAL, ...) \
458  TfEnum::_AddName(VAL, TF_PP_STRINGIZE(VAL), \
459  TfEnum::_NameIdent(__VA_ARGS__));
460 
462 
463 #endif // PXR_BASE_TF_ENUM_H
static TF_API bool IsKnownEnumType(const std::string &typeName)
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
typename std::enable_if< B, T >::type enable_if_t
Define Imath::enable_if_t to be std for C++14, equivalent for C++11.
TfEnum(const std::type_info &ti, int value)
Definition: enum.h:141
TfCStrHashWrapper TfHashAsCStr(char const *cstr)
Definition: hash.h:170
#define TF_API
Definition: api.h:23
bool operator>(const TfEnum &t) const
Definition: enum.h:175
friend std::enable_if_t< std::is_enum< T >::value, bool > operator!=(T val, TfEnum const &e)
Compare a literal enum value val of enum type T with TfEnum e.
Definition: enum.h:209
static std::vector< std::string > GetAllNames(TfEnum val)
Definition: enum.h:299
bool operator>=(const TfEnum &t) const
Definition: enum.h:181
TfEnum()
Default constructor assigns integer value zero.
Definition: enum.h:123
GLsizei const GLfloat * value
Definition: glcorearb.h:824
Definition: enum.h:119
static TF_API const std::type_info * GetTypeFromName(const std::string &typeName)
bool operator<=(const TfEnum &t) const
Definition: enum.h:169
std::enable_if_t< std::is_same< Enum, TfEnum >::value > TfHashAppend(HashState &h, Enum const &e)
Definition: enum.h:422
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
static char const * _NameIdent(char const *str=nullptr)
Definition: enum.h:379
static std::vector< std::string > GetAllNames()
Definition: enum.h:315
const std::type_info & GetType() const
Returns the type of the enum value, as an std::type_info.
Definition: enum.h:226
static TF_API std::string GetFullName(TfEnum val)
const int & GetValueAsInt() const
Returns the integral value of the enum value.
Definition: enum.h:231
GLuint const GLchar * name
Definition: glcorearb.h:786
GLdouble t
Definition: glad.h:2397
static void AddName(TfEnum val, const std::string &valName, const std::string &displayName="")
Definition: enum.h:383
bool IsA(const std::type_info &t) const
Definition: enum.h:221
TfEnum(T value, std::enable_if_t< std::is_enum< T >::value > *=0)
Initializes value to enum variable value of enum type T.
Definition: enum.h:130
static TF_API TfEnum GetValueFromFullName(const std::string &fullname, bool *foundIt=NULL)
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
friend std::enable_if_t< std::is_enum< T >::value, bool > operator==(T val, TfEnum const &e)
Compare a literal enum value val of enum type T with TfEnum e.
Definition: enum.h:202
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
TF_API std::ostream & operator<<(std::ostream &out, const TfEnum &e)
static TF_API std::string GetDisplayName(TfEnum val)
bool operator==(const TfEnum &t) const
True if *this and t have both the same type and value.
Definition: enum.h:147
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
std::enable_if_t< std::is_enum< T >::value, bool > operator==(T value) const
True if *this has been assigned with value.
Definition: enum.h:188
static TF_API std::string GetName(TfEnum val)
T GetValue() const
Definition: enum.h:247
PXR_NAMESPACE_OPEN_SCOPE bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
static TfEnum IntegralEnum(T value)
Definition: enum.h:390
static T GetValueFromName(const std::string &name, bool *foundIt=NULL)
Definition: enum.h:333
bool IsA() const
True if *this has been assigned any enumerated value of type T.
Definition: enum.h:215
bool operator!=(const TfEnum &t) const
Definition: enum.h:154
bool operator<(const TfEnum &t) const
Definition: enum.h:162
static TF_API void _AddName(TfEnum val, char const *valName, char const *displayName)
std::enable_if_t< std::is_enum< T >::value, bool > operator!=(T value) const
False if *this has been assigned with value.
Definition: enum.h:195