HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
APEX_Types.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: APEX_Types.h (APEX Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __APEX_TYPES_H__
12 #define __APEX_TYPES_H__
13 
14 #include "APEX_API.h"
15 #include "APEX_Include.h"
16 
17 #include <UT/UT_Array.h>
18 #include <UT/UT_ArrayMap.h>
19 #include <UT/UT_ArrayStringMap.h>
20 #include <UT/UT_Assert.h>
21 #include <UT/UT_Debug.h>
22 #include <UT/UT_StringHolder.h>
23 #include <SYS/SYS_StaticAssert.h>
24 #include <SYS/SYS_Compiler.h>
25 #include <SYS/SYS_Types.h>
26 #include <SYS/SYS_TypeTraits.h>
27 
28 #include <new>
29 #include <typeindex>
30 #include <typeinfo>
31 #include <utility>
32 
33 #include <stddef.h>
34 
35 namespace apex
36 {
37 
38 class APEX_Buffer;
39 class APEX_Graph;
40 class APEX_TypeDefinitionBase;
41 
43 
44 static constexpr UT_StringLit theUndefTypeName = "undefined";
45 static constexpr UT_StringLit theAnonTypeName = "anonymous";
46 static constexpr UT_StringLit theVariadicPrefix = "VariadicArg<";
47 static constexpr UT_StringLit theVariadicFormat = "VariadicArg<{}>";
48 static constexpr char theInplacePortPrefix[] = "*";
49 static constexpr char theSparePortPrefix[] = "+";
50 static constexpr char theConditionalInplacePortPrefix[] = "-";
51 static constexpr UT_StringLit theSparePortName = "__spare__";
52 static constexpr UT_StringLit theRunDataPortName = "rundata";
53 
55 {
56 public:
58 
59  /// Return the size of a single instance of the type, or 0 if the type is not well-defined (i.e. a void).
60  virtual size_t sizeT() const = 0;
61 
62  /// Return a human-readable string representing the type.
63  virtual const UT_StringRef &repr() const = 0;
64  /// Allocate a resizable array of the type. The current implementation uses a UT_Array behind-the-scenes, however
65  /// the implementation is type-erased to allow flexibility.
66  virtual void *allocate(exint size) const = 0;
67  /// Append a default-constructed instance to the array previously allocated by @ref allocate. If no allocation could be performed,
68  /// return -1.
69  virtual exint append(void *mem) const = 0;
70  /// Reset the instance of this type (member of buffer created in @ref allocate) to a default value if possible.
71  virtual void clear(void *mem) const = 0;
72  /// Free a resizable array created by @ref allocate.
73  virtual void deallocate(void *mem) const = 0;
74  /// Get a pointer to the @p{index}-th value in the resizable array created by @ref allocate stored at @p mem.
75  virtual void *getPtrAtIndex(void *mem, exint index) const = 0;
76 
77  virtual bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port) const = 0;
78  /// Copy the value at @p val to @p mem.
79  virtual void setData(void *mem, const void *val) const = 0;
80  /// If this is a compound type (such as variadics), return the type definition for the contained type.
81  virtual const APEX_TypeDefinitionBase *subTypeDef() const = 0;
82  /// Return the RTTI information for the contained type.
83  virtual std::type_index typeIndex() const = 0;
84  /// Return whether the type is copy-assignable (i.e. can @ref setData function).
85  virtual bool isCopyable() const = 0;
86  /// Return whether the type is an array
87  virtual bool isArray() const { return false; }
88  /// Return whether the type is a variadic arg
89  virtual bool isVariadic() const { return false; }
90  /// Return whether the type is a handle to some shared data (i.e. geometry)
91  virtual bool isHandle() const { return false; }
92 };
93 
94 /// Compile-time information about the default initialization to use for a type visible to the APEX type system.
95 template <typename T>
97 {
98  /// Return a default value for the type.
99  static T value() { return T(); }
100 
101  /// If this member is missing or false in a specialization, the default value is assumed to be
102  /// something other than T(), and any code that implicitly relies on that being the case will
103  /// static assert.
104  static constexpr bool isDefaultConstructing = true;
105 };
106 
107 template <>
109 {
110  static Vector2 value() { return Vector2(0.0, 0.0); }
111 };
112 
113 template <>
115 {
116  static Vector3 value() { return Vector3(0.0, 0.0, 0.0); }
117 };
118 
119 template <>
121 {
122  static Vector4 value() { return Vector4(0.0, 0.0, 0.0, 0.0); }
123 };
124 
125 template <>
127 {
128  static Matrix3 value() { return Matrix3(1.0); }
129 };
130 
131 template <>
133 {
134  static Matrix4 value() { return Matrix4(1.0); }
135 };
136 
137 namespace detail
138 {
139 
140 template <typename T, typename = void>
142 {
143 };
144 
145 template <typename T>
147  T,
148  SYS_Void_t<decltype(APEX_TypeDefault<T>::isDefaultConstructing)>>
149  : SYS_BoolConstant<APEX_TypeDefault<T>::isDefaultConstructing == false>
150 {
151 };
152 
153 template <typename T>
155 
156 }
157 
158 template <typename T>
159 static inline void *
160 allocateT(exint size)
161 {
162  auto *arr = new UT_Array<T>(size);
163  if constexpr (SYS_IsPod_v<T>)
164  {
165  arr->setSizeNoInit(size);
166  arr->constant(APEX_TypeDefault<T>::value());
167  }
168  else if constexpr (std::is_move_constructible_v<T>)
169  {
170  arr->setCapacity(size);
171  for (exint i = 0; i < size; ++i)
172  arr->emplace_back(APEX_TypeDefault<T>::value());
173  }
174  else
175  {
177  !detail::APEX_TypeDefaultIsSpecialized_v<T>, "A move constructor must be declared on a "
178  "type with an explicit APEX default value.");
179  arr->setSize(size);
180  }
181  return arr;
182 }
183 
184 template <typename T>
186 {
187 public:
188  /// Called to allocate a @c UT_Array<T> of length @p size.
189  static void *allocate(exint size) { return allocateT<T>(size); }
190  /// Called for each non-subport usage of a type with the buffer, graph and allocated port.
191  ///
192  /// Returns whether or not compilation was successful -- if it returns false, then compilation
193  /// is aborted. Error messages can be added into the passed graph with addError. For types which
194  /// handle their own subports (like VariadicArgs), validity of those subports must be checked
195  /// here; callbacks can do the same thing (usually with __spare__ ports) in their compile
196  /// callback.
197  static bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port) { return true; }
198  /// Given an initialized instance of `T`, reset it to the default state.
199  static void clear(T *mem)
200  {
201  // If we can assign the type to its default, use that. Despite the name of the type trait,
202  // this also catches copy assign operators (it's defined as whether assigning from an rvalue
203  // compiles, which is precisely what the guarded statement does -- there is no need to allow
204  // adding extra types to the condition as anything not std::is_move_assignable_v will not
205  // compile)
206  if constexpr (std::is_move_assignable_v<T>)
207  {
209  }
210  // If the type is not assignable, then destroy the old object and construct a new one in its
211  // place. If the destructor is trivial or the type was marked POD with SYS_DECLARE_IS_POD
212  // then the destructor call is skipped. Note that the apparent use of a move constructor
213  // here is not what it seems: due to the new rvalue semantics in C++17 (aka "guaranteed copy
214  // elision") the call to value() directly initializes the data in `mem` (almost as if it
215  // took a hidden destination pointer) so no temporary is ever made. This trick is not
216  // possible in the various UT_Array-dependent parts of the APEX type system, as they do not
217  // expose any API to manually call the constructors for new elements.
218  else
219  {
220  if constexpr (!std::is_trivially_destructible_v<T> && !SYS_IsPod_v<T>)
221  mem->~T();
222  new (static_cast<void *>(mem)) T(APEX_TypeDefault<T>::value());
223  }
224  }
225  static bool isHandle() { return false; }
226 };
227 
228 template <typename T, typename = void>
230 {
231 };
232 
233 /// Check if an APEX type wraps another type (for example, @ref VariadicArg)
234 template <typename T>
236 {
237 };
238 
239 // The idea behind this overload is to support callbacks that perform
240 // 'graph-compile-time' type resolution, resolving the underlying types
241 // connected data. This class enables higher level tooling to treat
242 // these callbacks and their signatures in the same way as well-defined
243 // types whilst also being able to detect whether special allocation or
244 // compilation steps are necessary.
245 // For an example see the APEX_CopyArg callback in APEX_Callback.h
247 {
248 public:
250  : myTypeName("void")
251  , mySubTypeDef(nullptr)
252  , myTypeIndex(std::type_index(typeid(void)))
253  {
254  auto key = typeid(void).name();
256  ? APEXtypeDefinitions()[key]->repr() == myTypeName
257  : true);
258  APEXtypeDefinitions()[key] = this;
259  }
260 
262 
263  size_t sizeT() const override { return 0; }
264  const UT_StringRef &repr() const override { return myTypeName.asRef(); }
265  void *allocate(exint size) const override { return nullptr; }
266  void clear(void *mem) const override {}
267  exint append(void *mem) const override { return -1; }
268  void deallocate(void *mem) const override {}
269  void *getPtrAtIndex(void *mem, exint index) const override { return nullptr; }
270  void setData(void *mem, const void *val) const override {}
271  bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port) const override { return true; }
272  const APEX_TypeDefinitionBase *subTypeDef() const override { return mySubTypeDef; }
273  std::type_index typeIndex() const override { return myTypeIndex; }
274  bool isCopyable() const override { return false; };
275 
276 private:
277  const UT_StringLit myTypeName;
278  const APEX_TypeDefinitionBase *mySubTypeDef;
279  std::type_index myTypeIndex;
280 };
281 
282 template <typename>
284 {
285 };
286 
287 template <typename T> class ApexArray;
288 
289 template <typename T>
291 {
292 };
293 
294 template <typename>
296 {
297 };
298 
299 
300 template <typename T>
302 {
303 };
304 
305 template <typename T>
307 {
308 public:
310  : myTypeName(type_name)
311  , mySubTypeDef(nullptr)
312  , myTypeIndex(std::type_index(typeid(T)))
313  {
314  // UTdebugPrint(type_name, std::is_copy_assignable_v<T>, std::is_copy_constructible_v<T>);
315  auto key = typeid(T).name();
317  ? APEXtypeDefinitions()[key]->repr() == myTypeName
318  : true);
319  if (!APEXtypeDefinitions().contains(key))
320  APEXtypeDefinitions()[key] = this;
321  if constexpr (APEX_IsCompoundType<T>::value)
322  {
323  auto sub_key = typeid(typename T::value_type).name();
324  if (APEXtypeDefinitions().contains(sub_key))
325  {
326  mySubTypeDef = APEXtypeDefinitions()[sub_key];
327  }
328  }
329  }
330 
331  ~APEX_TypeDefinition() override {}
332 
333  typedef T value_type;
334 
335  const UT_StringRef &repr() const override { return myTypeName.asRef(); }
336 
337  size_t sizeT() const override { return sizeof(T); }
338 
339  void *allocate(exint size) const override
340  {
341  return APEX_TypeTraits<T>::allocate(size);
342  }
343 
344  void clear(void *mem) const override
345  {
346  APEX_TypeTraits<T>::clear(reinterpret_cast<T *>(mem));
347  }
348 
349  exint append(void *mem) const override
350  {
351  UT_Array<T> *buffer_arr = reinterpret_cast<UT_Array<T> *>(mem);
352  exint index = -1;
353  if constexpr (std::is_move_assignable_v<T>)
354  index = buffer_arr->emplace_back(APEX_TypeDefault<T>::value());
355  else
356  {
358  !detail::APEX_TypeDefaultIsSpecialized_v<T>,
359  "A move constructor must be declared on a type with an explicit APEX default "
360  "value.");
361  index = buffer_arr->emplace_back();
362  }
363  return index;
364  }
365 
366  void deallocate(void *mem) const override
367  {
368  UT_Array<T> *buffer_arr = reinterpret_cast<UT_Array<T> *>(mem);
369  delete buffer_arr;
370  }
371 
372  void *getPtrAtIndex(void *mem, exint index) const override
373  {
374  UT_Array<T> &buffer_arr = *reinterpret_cast<UT_Array<T> *>(mem);
375  return &buffer_arr[index];
376  }
377 
378  void setData(SYS_MAYBE_UNUSED void *mem, SYS_MAYBE_UNUSED const void *val) const override
379  {
380  if constexpr (std::is_copy_assignable_v<T>)
381  {
382  const T *typed_val = reinterpret_cast<const T *>(val);
383  T *buffer_value = reinterpret_cast<T *>(mem);
384  *buffer_value = *typed_val;
385  }
386  else
387  UTdebugPrint("cannot copy assign", myTypeName);
388  }
389 
390  bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port) const override
391  {
392  return APEX_TypeTraits<T>::compile(buffer, graph, port);
393  }
394 
395  std::type_index typeIndex() const override { return myTypeIndex; }
396  bool isCopyable() const override { return std::is_copy_assignable_v<T>; }
397 
398  bool isArray() const override { return APEX_IsArrayType<T>::value; }
399  bool isVariadic() const override { return APEX_IsVariadicType<T>::value; }
400  bool isHandle() const override { return APEX_TypeTraits<T>::isHandle(); }
401 
402  const APEX_TypeDefinitionBase *subTypeDef() const override { return mySubTypeDef; }
403 
404 private:
405  const UT_StringLit myTypeName;
406  const APEX_TypeDefinitionBase *mySubTypeDef;
407  std::type_index myTypeIndex;
408 };
409 
410 template <>
412 {
413 };
414 
415 /// Return the type definition for a compile-time known type. APEX equivalent of @c typeid().
416 template <typename T>
417 static const APEX_TypeDefinitionBase *
418 findTypeDef()
419 {
420  auto key = typeid(T).name();
421  auto it = APEXtypeDefinitions().find(key);
422  if (!it.atEnd())
423  return it->second;
424  // UTdebugPrint("findTypeDef could not find:", key);
425  return nullptr;
426 }
427 
428 /// Lookup a type definition by its @c repr().
429 static const APEX_TypeDefinitionBase *
430 findTypeDef(const UT_StringRef &type_name)
431 {
432  // trying to lookup an anonymous type by name should return nothing
433  if (type_name == theAnonTypeName)
434  return nullptr;
435  for (auto it = APEXtypeDefinitions().begin(); !it.atEnd(); ++it)
436  {
437  if (it->second->repr() == type_name)
438  return it->second;
439  }
440  return nullptr;
441 }
442 
443 /// Return the @c repr() name for a compile-time known type.
444 template <typename T>
445 static const UT_StringRef &
446 findTypeName()
447 {
448  auto key = typeid(T).name();
449  auto it = APEXtypeDefinitions().find(key);
450  if (!it.atEnd())
451  return it->second->repr();
452  return theUndefTypeName.asRef();
453 }
454 
455 static bool
456 isVariadicType(const APEX_TypeDefinitionBase *type)
457 {
458  return type && type->isVariadic();
459 }
460 
461 // Check if copyArgData will attempt to perform a copy, or whether it will fail
462 // due to type issues.
463 static bool
464 canCopyArgData(
465  const APEX_TypeDefinitionBase *dst,
466  const APEX_TypeDefinitionBase *src,
467  bool allow_implicit_conversion = false)
468 {
469  if (dst != src)
470  {
471  if (!allow_implicit_conversion)
472  return false;
473  if (dst == findTypeDef<Bool>() && src == findTypeDef<Int>())
474  return true;
475  if (src == findTypeDef<Bool>() && dst == findTypeDef<Int>())
476  return true;
477  return false;
478  }
479  return dst->isCopyable();
480 }
481 
482 #define APEX_DEF_TYPE_NAME(t) static APEX_TypeDefinition<t> t_dfn_##t{ #t };
483 #define APEX_DEF_TYPE_NAME_N(t, n) static APEX_TypeDefinition<t> t_dfn_##n{ #t };
484 #define APEX_DEF_TYPE_RUNDATA(c) \
485  inline static APEX_TypeDefinition<RunData> t_dfn_##c{ #c"::RunData" };
486 
487 /// Defines the type, its array, and variadic arg variants at the same time
488 #define APEX_DEF_TYPE_NAME_BASIC(type) \
489  APEX_DEF_TYPE_NAME(type) \
490  APEX_DEF_TYPE_NAME_N(VariadicArg<type>, VariadicArg_##type) \
491  /**/
492 #define APEX_DEF_TYPE_NAME_FULL(type) \
493  APEX_DEF_TYPE_NAME_BASIC(type) \
494  APEX_DEF_TYPE_NAME(type##Array) \
495  APEX_DEF_TYPE_NAME_N(VariadicArg<type##Array>, VariadicArg_##type##Array) \
496  /**/
497 
498 APEX_API extern APEX_VoidTypeDefinition void_type_defn;
499 
500 } // namespace apex
501 
502 #endif // end header guard
~APEX_TypeDefinition() override
Definition: APEX_Types.h:331
std::type_index typeIndex() const override
Return the RTTI information for the contained type.
Definition: APEX_Types.h:395
bool isCopyable() const override
Return whether the type is copy-assignable (i.e. can setData function).
Definition: APEX_Types.h:396
virtual bool isCopyable() const =0
Return whether the type is copy-assignable (i.e. can setData function).
void * getPtrAtIndex(void *mem, exint index) const override
Get a pointer to the {index}-th value in the resizable array created by allocate stored at mem...
Definition: APEX_Types.h:269
virtual std::type_index typeIndex() const =0
Return the RTTI information for the contained type.
virtual void * allocate(exint size) const =0
#define UTdebugPrint(...)
Definition: UT_Debug.h:146
APEX_API UT_ArrayStringMap< const APEX_TypeDefinitionBase * > & APEXtypeDefinitions()
virtual bool isArray() const
Return whether the type is an array.
Definition: APEX_Types.h:87
UT_Vector4T< Float > Vector4
Definition: APEX_Include.h:66
void
Definition: png.h:1083
#define SYS_STATIC_ASSERT_MSG(expr, msg)
Compile-time information about the default initialization to use for a type visible to the APEX type ...
Definition: APEX_Types.h:96
GLsizei const GLfloat * value
Definition: glcorearb.h:824
void SYS_Void_t
Alternative for C++17's std::void that can be used in C++14:
void setSizeNoInit(exint newsize)
Definition: UT_Array.h:702
void * getPtrAtIndex(void *mem, exint index) const override
Get a pointer to the {index}-th value in the resizable array created by allocate stored at mem...
Definition: APEX_Types.h:372
#define SYS_MAYBE_UNUSED
Definition: SYS_Compiler.h:71
#define APEX_API
Definition: APEX_API.h:21
void clear(void *mem) const override
Reset the instance of this type (member of buffer created in allocate) to a default value if possible...
Definition: APEX_Types.h:266
const UT_StringRef & repr() const override
Return a human-readable string representing the type.
Definition: APEX_Types.h:335
int64 exint
Definition: SYS_Types.h:125
bool isVariadic() const override
Return whether the type is a variadic arg.
Definition: APEX_Types.h:399
APEX_API APEX_VoidTypeDefinition void_type_defn
void * allocate(exint size) const override
Definition: APEX_Types.h:339
virtual void clear(void *mem) const =0
Reset the instance of this type (member of buffer created in allocate) to a default value if possible...
3D Vector class.
4D Vector class.
Definition: UT_Vector4.h:174
2D Vector class.
Definition: UT_Vector2.h:159
GLuint buffer
Definition: glcorearb.h:660
uint64 value_type
Definition: GA_PrimCompat.h:29
Holds all of the memory for execution state of a compiled APEX graph.
Definition: APEX_Buffer.h:96
constexpr auto APEX_TypeDefaultIsSpecialized_v
Definition: APEX_Types.h:154
void * allocate(exint size) const override
Definition: APEX_Types.h:265
virtual exint append(void *mem) const =0
void deallocate(void *mem) const override
Free a resizable array created by allocate.
Definition: APEX_Types.h:366
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
exint emplace_back(S &&...s)
Definition: UT_ArrayImpl.h:769
virtual void deallocate(void *mem) const =0
Free a resizable array created by allocate.
static constexpr bool isDefaultConstructing
Definition: APEX_Types.h:104
virtual const UT_StringRef & repr() const =0
Return a human-readable string representing the type.
const APEX_TypeDefinitionBase * subTypeDef() const override
If this is a compound type (such as variadics), return the type definition for the contained type...
Definition: APEX_Types.h:402
constexpr std::enable_if< I< type_count_base< T >::value, int >::type tuple_type_size(){return subtype_count< typename std::tuple_element< I, T >::type >::value+tuple_type_size< T, I+1 >);}template< typename T > struct type_count< T, typename std::enable_if< is_tuple_like< T >::value >::type >{static constexpr int value{tuple_type_size< T, 0 >)};};template< typename T > struct subtype_count{static constexpr int value{is_mutable_container< T >::value?expected_max_vector_size:type_count< T >::value};};template< typename T, typename Enable=void > struct type_count_min{static const int value{0};};template< typename T >struct type_count_min< T, typename std::enable_if<!is_mutable_container< T >::value &&!is_tuple_like< T >::value &&!is_wrapper< T >::value &&!is_complex< T >::value &&!std::is_void< T >::value >::type >{static constexpr int value{type_count< T >::value};};template< typename T > struct type_count_min< T, typename std::enable_if< is_complex< T >::value >::type >{static constexpr int value{1};};template< typename T >struct type_count_min< T, typename std::enable_if< is_wrapper< T >::value &&!is_complex< T >::value &&!is_tuple_like< T >::value >::type >{static constexpr int value{subtype_count_min< typename T::value_type >::value};};template< typename T, std::size_t I >constexpr typename std::enable_if< I==type_count_base< T >::value, int >::type tuple_type_size_min(){return 0;}template< typename T, std::size_t I > constexpr typename std::enable_if< I< type_count_base< T >::value, int >::type tuple_type_size_min(){return subtype_count_min< typename std::tuple_element< I, T >::type >::value+tuple_type_size_min< T, I+1 >);}template< typename T > struct type_count_min< T, typename std::enable_if< is_tuple_like< T >::value >::type >{static constexpr int value{tuple_type_size_min< T, 0 >)};};template< typename T > struct subtype_count_min{static constexpr int value{is_mutable_container< T >::value?((type_count< T >::value< expected_max_vector_size)?type_count< T >::value:0):type_count_min< T >::value};};template< typename T, typename Enable=void > struct expected_count{static const int value{0};};template< typename T >struct expected_count< T, typename std::enable_if<!is_mutable_container< T >::value &&!is_wrapper< T >::value &&!std::is_void< T >::value >::type >{static constexpr int value{1};};template< typename T > struct expected_count< T, typename std::enable_if< is_mutable_container< T >::value >::type >{static constexpr int value{expected_max_vector_size};};template< typename T >struct expected_count< T, typename std::enable_if<!is_mutable_container< T >::value &&is_wrapper< T >::value >::type >{static constexpr int value{expected_count< typename T::value_type >::value};};enum class object_category:int{char_value=1, integral_value=2, unsigned_integral=4, enumeration=6, boolean_value=8, floating_point=10, number_constructible=12, double_constructible=14, integer_constructible=16, string_assignable=23, string_constructible=24, other=45, wrapper_value=50, complex_number=60, tuple_value=70, container_value=80,};template< typename T, typename Enable=void > struct classify_object{static constexpr object_category value{object_category::other};};template< typename T >struct classify_object< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, char >::value &&std::is_signed< T >::value &&!is_bool< T >::value &&!std::is_enum< T >::value >::type >{static constexpr object_category value{object_category::integral_value};};template< typename T >struct classify_object< T, typename std::enable_if< std::is_integral< T >::value &&std::is_unsigned< T >::value &&!std::is_same< T, char >::value &&!is_bool< T >::value >::type >{static constexpr object_category value{object_category::unsigned_integral};};template< typename T >struct classify_object< T, typename std::enable_if< std::is_same< T, char >::value &&!std::is_enum< T >::value >::type >{static constexpr object_category value{object_category::char_value};};template< typename T > struct classify_object< T, typename std::enable_if< is_bool< T >::value >::type >{static constexpr object_category value{object_category::boolean_value};};template< typename T > struct classify_object< T, typename std::enable_if< std::is_floating_point< T >::value >::type >{static constexpr object_category value{object_category::floating_point};};template< typename T >struct classify_object< T, typename std::enable_if<!std::is_floating_point< T >::value &&!std::is_integral< T >::value &&std::is_assignable< T &, std::string >::value >::type >{static constexpr object_category value{object_category::string_assignable};};template< typename T >struct classify_object< T, typename std::enable_if<!std::is_floating_point< T >::value &&!std::is_integral< T >::value &&!std::is_assignable< T &, std::string >::value &&(type_count< T >::value==1)&&std::is_constructible< T, std::string >::value >::type >{static constexpr object_category value{object_category::string_constructible};};template< typename T > struct classify_object< T, typename std::enable_if< std::is_enum< T >::value >::type >{static constexpr object_category value{object_category::enumeration};};template< typename T > struct classify_object< T, typename std::enable_if< is_complex< T >::value >::type >{static constexpr object_category value{object_category::complex_number};};template< typename T > struct uncommon_type{using type=typename std::conditional<!std::is_floating_point< T >::value &&!std::is_integral< T >::value &&!std::is_assignable< T &, std::string >::value &&!std::is_constructible< T, std::string >::value &&!is_complex< T >::value &&!is_mutable_container< T >::value &&!std::is_enum< T >::value, std::true_type, std::false_type >::type;static constexpr bool value=type::value;};template< typename T >struct classify_object< T, typename std::enable_if<(!is_mutable_container< T >::value &&is_wrapper< T >::value &&!is_tuple_like< T >::value &&uncommon_type< T >::value)>::type >{static constexpr object_category value{object_category::wrapper_value};};template< typename T >struct classify_object< T, typename std::enable_if< uncommon_type< T >::value &&type_count< T >::value==1 &&!is_wrapper< T >::value &&is_direct_constructible< T, double >::value &&is_direct_constructible< T, int >::value >::type >{static constexpr object_category value{object_category::number_constructible};};template< typename T >struct classify_object< T, typename std::enable_if< uncommon_type< T >::value &&type_count< T >::value==1 &&!is_wrapper< T >::value &&!is_direct_constructible< T, double >::value &&is_direct_constructible< T, int >::value >::type >{static constexpr object_category value{object_category::integer_constructible};};template< typename T >struct classify_object< T, typename std::enable_if< uncommon_type< T >::value &&type_count< T >::value==1 &&!is_wrapper< T >::value &&is_direct_constructible< T, double >::value &&!is_direct_constructible< T, int >::value >::type >{static constexpr object_category value{object_category::double_constructible};};template< typename T >struct classify_object< T, typename std::enable_if< is_tuple_like< T >::value &&((type_count< T >::value >=2 &&!is_wrapper< T >::value)||(uncommon_type< T >::value &&!is_direct_constructible< T, double >::value &&!is_direct_constructible< T, int >::value)||(uncommon_type< T >::value &&type_count< T >::value >=2))>::type >{static constexpr object_category value{object_category::tuple_value};};template< typename T > struct classify_object< T, typename std::enable_if< is_mutable_container< T >::value >::type >{static constexpr object_category value{object_category::container_value};};template< typename T, enable_if_t< classify_object< T >::value==object_category::char_value, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"CHAR";}template< typename T, enable_if_t< classify_object< T >::value==object_category::integral_value||classify_object< T >::value==object_category::integer_constructible, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"INT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::unsigned_integral, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"UINT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::floating_point||classify_object< T >::value==object_category::number_constructible||classify_object< T >::value==object_category::double_constructible, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"FLOAT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::enumeration, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"ENUM";}template< typename T, enable_if_t< classify_object< T >::value==object_category::boolean_value, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"BOOLEAN";}template< typename T, enable_if_t< classify_object< T >::value==object_category::complex_number, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"COMPLEX";}template< typename T, enable_if_t< classify_object< T >::value >=object_category::string_assignable &&classify_object< T >::value<=object_category::other, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"TEXT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::tuple_value &&type_count_base< T >::value >=2, detail::enabler >=detail::dummy >std::string type_name();template< typename T, enable_if_t< classify_object< T >::value==object_category::container_value||classify_object< T >::value==object_category::wrapper_value, detail::enabler >=detail::dummy >std::string type_name();template< typename T, enable_if_t< classify_object< T >::value==object_category::tuple_value &&type_count_base< T >::value==1, detail::enabler >=detail::dummy >inline std::string type_name(){return type_name< typename std::decay< typename std::tuple_element< 0, T >::type >::type >);}template< typename T, std::size_t I >inline typename std::enable_if< I==type_count_base< T >::value, std::string >::type tuple_name(){return std::string{};}template< typename T, std::size_t I >inline typename std::enable_if<(I< type_count_base< T >::value), std::string >::type tuple_name(){auto str=std::string{type_name< typename std::decay< typename std::tuple_element< I, T >::type >::type >)}+ ','+tuple_name< T, I+1 >);if(str.back()== ',') str.pop_back();return str;}template< typename T, enable_if_t< classify_object< T >::value==object_category::tuple_value &&type_count_base< T >::value >=2, detail::enabler > > std::string type_name()
Recursively generate the tuple type name.
Definition: CLI11.h:1729
UT_Matrix3T< Float > Matrix3
Definition: APEX_Include.h:67
exint append(void *mem) const override
Definition: APEX_Types.h:349
UN_PortID APEX_PortID
Definition: APEX_Include.h:335
bool isHandle() const override
Return whether the type is a handle to some shared data (i.e. geometry)
Definition: APEX_Types.h:400
UT_Matrix4T< Float > Matrix4
Definition: APEX_Include.h:68
exint append(void *mem) const override
Definition: APEX_Types.h:267
virtual void setData(void *mem, const void *val) const =0
Copy the value at val to mem.
GLuint const GLchar * name
Definition: glcorearb.h:786
static void * allocate(exint size)
Called to allocate a UT_Array<T> of length size.
Definition: APEX_Types.h:189
virtual bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port) const =0
const APEX_TypeDefinitionBase * subTypeDef() const override
If this is a compound type (such as variadics), return the type definition for the contained type...
Definition: APEX_Types.h:272
size_t sizeT() const override
Return the size of a single instance of the type, or 0 if the type is not well-defined (i...
Definition: APEX_Types.h:263
void clear(void *mem) const override
Reset the instance of this type (member of buffer created in allocate) to a default value if possible...
Definition: APEX_Types.h:344
static T value()
Return a default value for the type.
Definition: APEX_Types.h:99
void deallocate(void *mem) const override
Free a resizable array created by allocate.
Definition: APEX_Types.h:268
virtual const APEX_TypeDefinitionBase * subTypeDef() const =0
If this is a compound type (such as variadics), return the type definition for the contained type...
SYS_FORCE_INLINE const UT_StringRef & asRef() const
GLsizeiptr size
Definition: glcorearb.h:664
GLenum GLenum dst
Definition: glcorearb.h:1793
const UT_StringRef & repr() const override
Return a human-readable string representing the type.
Definition: APEX_Types.h:264
UT_Vector2T< Float > Vector2
Definition: APEX_Include.h:64
static bool isHandle()
Definition: APEX_Types.h:225
bool isCopyable() const override
Return whether the type is copy-assignable (i.e. can setData function).
Definition: APEX_Types.h:274
GLuint index
Definition: glcorearb.h:786
GLuint GLfloat * val
Definition: glcorearb.h:1608
void setData(SYS_MAYBE_UNUSED void *mem, SYS_MAYBE_UNUSED const void *val) const override
Definition: APEX_Types.h:378
virtual bool isVariadic() const
Return whether the type is a variadic arg.
Definition: APEX_Types.h:89
static void clear(T *mem)
Given an initialized instance of T, reset it to the default state.
Definition: APEX_Types.h:199
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port) const override
Definition: APEX_Types.h:390
UT_Vector3T< Float > Vector3
Definition: APEX_Include.h:65
bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port) const override
Definition: APEX_Types.h:271
virtual void * getPtrAtIndex(void *mem, exint index) const =0
Get a pointer to the {index}-th value in the resizable array created by allocate stored at mem...
std::type_index typeIndex() const override
Return the RTTI information for the contained type.
Definition: APEX_Types.h:273
bool OIIO_UTIL_API contains(string_view a, string_view b)
Does 'a' contain the string 'b' within it?
void setData(void *mem, const void *val) const override
Copy the value at val to mem.
Definition: APEX_Types.h:270
static bool compile(APEX_Buffer *buffer, APEX_Graph *graph, APEX_PortID port)
Definition: APEX_Types.h:197
bool isArray() const override
Return whether the type is an array.
Definition: APEX_Types.h:398
size_t sizeT() const override
Return the size of a single instance of the type, or 0 if the type is not well-defined (i...
Definition: APEX_Types.h:337
virtual bool isHandle() const
Return whether the type is a handle to some shared data (i.e. geometry)
Definition: APEX_Types.h:91
APEX_TypeDefinition(const UT_StringLit &&type_name)
Definition: APEX_Types.h:309
GLenum src
Definition: glcorearb.h:1793
virtual size_t sizeT() const =0
Return the size of a single instance of the type, or 0 if the type is not well-defined (i...
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566