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