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, std::move( movable ) }
75  {
76  }
77  UT_SmallArray(UT_SmallArray &&movable) noexcept
78  : UT_Array<T>{ UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS }
79  {
81  UT_Array<T>::operator=(std::move(movable));
82  }
83  /// @}
84 
85  /// Initializer list constructor
86  /// If you are wondering why we mark this as explicit...
87  /// Imagine you have the following:
88  /// void foo(int i); // 1
89  /// void foo(UT_SmallArray<int>); // 2
90  /// Without explicit you can do this
91  /// foo({1})
92  /// and function 1 will be called when you probably meant
93  /// for function 2 to be called.
94  explicit UT_SmallArray(std::initializer_list<T> init)
95  : UT_Array<T>( UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS )
96  {
99  }
100 
101 #undef UT_SMALL_ARRAY_SIZE_ASSERT
102 
103  /// Assignment operator
104  /// @{
107  {
108  UT_Array<T>::operator=(copy); // NOLINT
109  return *this;
110  }
112  operator=(const UT_Array<T> &copy)
113  {
115  return *this;
116  }
117  /// @}
118 
119  /// Move operator
120  /// @{
123  {
124  UT_Array<T>::operator=(std::move(movable));
125  return *this;
126  }
128  operator=(UT_Array<T> &&movable)
129  {
130  UT_Array<T>::operator=(std::move(movable));
131  return *this;
132  }
133  /// @}
134 
136  operator=(std::initializer_list<T> src)
137  {
139  return *this;
140  }
141 private:
142  alignas(T) char myBuffer[MAX_ELEMS*sizeof(T)];
143 };
144 
145 // For UT::ArraySet.
146 namespace UT
147 {
148 template <typename T>
149 struct DefaultClearer;
150 
151 template <typename T, size_t BYTES>
152 struct DefaultClearer<UT_SmallArray<T, BYTES>>
153 {
155  {
156  // Just in case, destruct and reconstruct,
157  // instead of using setCapacity(0).
159  p->~UT_SmallArray<T, BYTES>();
160  new ((void *)p) UT_SmallArray<T, BYTES>();
161  }
162  static bool isClear(const UT_SmallArray<T, BYTES> &v)
163  {
164  return v.isEmpty();
165  }
167  {
168  new ((void *)p) UT_SmallArray<T, BYTES>();
169  }
170  static const bool clearNeedsDestruction = false;
171 };
172 } // namespace UT
173 
174 // UT_SmallArray<T> is unsafe for trivial relocation
175 // because its UT_Array<T> part holds a pointer to
176 // UT_SmallArray<T>'s local buffer 'myBuffer'.
177 template <typename T>
179 
180 #endif // __UT_SMALLARRAY_H_INCLUDED__
#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(const UT_Array< T > &copy)
Definition: UT_SmallArray.h:57
static void clearConstruct(UT_SmallArray< T, BYTES > *p)
static constexpr struct UT_ArrayCT::ExternalCapacity EXTERNAL_CAPACITY
static void clear(UT_SmallArray< T, BYTES > &v)
UT_SmallArray(UT_Array< T > &&movable) noexcept
Definition: UT_SmallArray.h:73
#define SYS_DECLARE_IS_NOT_TR_TEMPLATE(...)
Version for class template.
static constexpr struct UT_ArrayCT::ExternalMove EXTERNAL_MOVE
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
bool isEmpty() const
Returns true iff there are no occupied elements in the array.
Definition: UT_Array.h:650
GLenum src
Definition: glcorearb.h:1793