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