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