HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_SmallArray.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: UT_SmallArray.h (UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #pragma once
12 
13 #ifndef __UT_SMALLARRAY_H_INCLUDED__
14 #define __UT_SMALLARRAY_H_INCLUDED__
15 
16 #include "UT_API.h"
17 #include "UT_Array.h"
18 #include "UT_Assert.h"
19 #include <SYS/SYS_Compiler.h>
20 #include <SYS/SYS_StaticAssert.h>
21 #include <SYS/SYS_TypeDecorate.h>
22 #include <utility>
23 #include <stddef.h>
24 
25 /// An array class with the small buffer optimization, making it ideal for
26 /// cases when you know it will only contain a few elements at the expense of
27 /// increasing the object size by MAX_BYTES (subject to alignment).
28 template <typename T, size_t MAX_BYTES = 64>
30 {
31  // As many elements that fit into MAX_BYTES with 1 item minimum
32  enum { MAX_ELEMS = MAX_BYTES/sizeof(T) < 1 ? 1 : MAX_BYTES/sizeof(T) };
33 
34 public:
35 
36 // gcc and clang (18+) warn about our use of offsetof() on non-POD types. We
37 // can't easily suppress this because it has to be done in the caller at
38 // instantiation time. Instead, punt to a runtime check instead.
39 #if !defined(__clang__) && defined(_MSC_VER)
40  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
41  using ThisT = UT_SmallArray<T,MAX_BYTES>; \
42  SYS_STATIC_ASSERT(offsetof(ThisT, myBuffer) == sizeof(UT_Array<T>))
43 #else
44  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
45  UT_ASSERT_P(!UT_Array<T>::isHeapBuffer());
46 #endif
47 
48  /// Default construction
50  : UT_Array<T>(UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS)
51  {
53  }
54 
55  /// Copy constructor
56  /// @{
57  explicit UT_SmallArray(const UT_Array<T> &copy)
58  : UT_Array<T>(UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS)
59  {
62  }
63  explicit UT_SmallArray(const UT_SmallArray &copy)
64  : UT_Array<T>(UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS)
65  {
68  }
69  /// @}
70 
71  /// Move constructor
72  /// @{
73  UT_SmallArray(UT_Array<T> &&movable) noexcept
74  : UT_Array<T>(UT_ArrayCT::EXTERNAL_MOVE, (T*)myBuffer, MAX_ELEMS,
75  std::move(movable))
76  {
77  }
78  UT_SmallArray(UT_SmallArray &&movable) noexcept
79  : UT_Array<T>(UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS)
80  {
82  UT_Array<T>::operator=(std::move(movable));
83  }
84  /// @}
85 
86  /// Initializer list constructor
87  /// If you are wondering why we mark this as explicit...
88  /// Imagine you have the following:
89  /// void foo(int i); // 1
90  /// void foo(UT_SmallArray<int>); // 2
91  /// Without explicit you can do this
92  /// foo({1})
93  /// and function 1 will be called when you probably meant
94  /// for function 2 to be called.
95  explicit UT_SmallArray(std::initializer_list<T> init)
96  : UT_Array<T>( UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS )
97  {
100  }
101 
102 #undef UT_SMALL_ARRAY_SIZE_ASSERT
103 
104  /// Assignment operator
105  /// @{
108  {
109  UT_Array<T>::operator=(copy); // NOLINT
110  return *this;
111  }
114  {
116  return *this;
117  }
118  /// @}
119 
120  /// Move operator
121  /// @{
124  {
125  UT_Array<T>::operator=(std::move(movable));
126  return *this;
127  }
130  {
131  UT_Array<T>::operator=(std::move(movable));
132  return *this;
133  }
134  /// @}
135 
137  operator=(std::initializer_list<T> src)
138  {
140  return *this;
141  }
142 private:
143  alignas(T) char myBuffer[MAX_ELEMS*sizeof(T)];
144 };
145 
146 // For UT::ArraySet.
147 namespace UT
148 {
149 template <typename T>
150 struct DefaultClearer;
151 
152 template <typename T, size_t BYTES>
154 {
156  {
157  // Just in case, destruct and reconstruct,
158  // instead of using setCapacity(0).
160  p->~UT_SmallArray<T, BYTES>();
161  new ((void *)p) UT_SmallArray<T, BYTES>();
162  }
163  static bool isClear(const UT_SmallArray<T, BYTES> &v)
164  {
165  return v.isEmpty();
166  }
168  {
169  new ((void *)p) UT_SmallArray<T, BYTES>();
170  }
171  static const bool clearNeedsDestruction = false;
172 };
173 } // namespace UT
174 
175 // UT_SmallArray<T> is unsafe for trivial relocation
176 // because its UT_Array<T> part holds a pointer to
177 // UT_SmallArray<T>'s local buffer 'myBuffer'.
178 template <typename T>
180 
181 #endif // __UT_SMALLARRAY_H_INCLUDED__
UT_SmallArray(UT_SmallArray &&movable) noexcept
Definition: UT_SmallArray.h:78
UT_SmallArray< T, MAX_BYTES > & operator=(UT_Array< T > &&movable)
UT_SmallArray< T, MAX_BYTES > & operator=(const UT_Array< T > &copy)
#define UT_SMALL_ARRAY_SIZE_ASSERT()
Definition: UT_SmallArray.h:44
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
const GLdouble * v
Definition: glcorearb.h:837
UT_Array< T > & operator=(const UT_Array< T > &a)
UT_SmallArray< T, MAX_BYTES > & operator=(UT_SmallArray< T, MAX_BYTES > &&movable)
UT_SmallArray(const UT_Array< T > &copy)
Definition: UT_SmallArray.h:57
static void clearConstruct(UT_SmallArray< T, BYTES > *p)
static void clear(UT_SmallArray< T, BYTES > &v)
UT_SmallArray< T, MAX_BYTES > & operator=(const UT_SmallArray< T, MAX_BYTES > &copy)
UT_SmallArray(UT_Array< T > &&movable) noexcept
Definition: UT_SmallArray.h:73
#define SYS_DECLARE_IS_NOT_TR_TEMPLATE(...)
Version for class template.
UT_SmallArray(std::initializer_list< T > init)
Definition: UT_SmallArray.h:95
UT_SmallArray()
Default construction.
Definition: UT_SmallArray.h:49
#define UT_API_TMPL
Definition: UT_API.h:15
static bool isClear(const UT_SmallArray< T, BYTES > &v)
UT_SmallArray(const UT_SmallArray &copy)
Definition: UT_SmallArray.h:63
UT_SmallArray< T, MAX_BYTES > & operator=(std::initializer_list< T > src)
bool isEmpty() const
Returns true iff there are no occupied elements in the array.
Definition: UT_Array.h:657
GLenum src
Definition: glcorearb.h:1793