Zserio C++ runtime library  1.3.0
Built for Zserio 2.18.0
AnyHolder.h
Go to the documentation of this file.
1 #ifndef ZSERIO_ANY_HOLDER_H_INC
2 #define ZSERIO_ANY_HOLDER_H_INC
3 
4 #include <type_traits>
5 
8 #include "zserio/NoInit.h"
10 #include "zserio/RebindAlloc.h"
11 #include "zserio/Traits.h"
12 #include "zserio/Types.h"
13 
14 namespace zserio
15 {
16 
17 namespace detail
18 {
19 
20 class TypeIdHolder
21 {
22 public:
23  using type_id = const int*;
24 
25  template <typename T>
26  static type_id get()
27  {
28  static int currentTypeId;
29 
30  return &currentTypeId;
31  }
32 };
33 
34 // Interface for object holders
35 template <typename ALLOC>
36 class IHolder
37 {
38 public:
39  virtual ~IHolder() = default;
40  virtual IHolder* clone(const ALLOC& allocator) const = 0;
41  virtual IHolder* clone(NoInitT, const ALLOC& allocator) const = 0;
42  virtual IHolder* clone(void* storage) const = 0;
43  virtual IHolder* clone(NoInitT, void* storage) const = 0;
44  virtual IHolder* move(const ALLOC& allocator) = 0;
45  virtual IHolder* move(NoInitT, const ALLOC& allocator) = 0;
46  virtual IHolder* move(void* storage) = 0;
47  virtual IHolder* move(NoInitT, void* storage) = 0;
48  virtual void destroy(const ALLOC& allocator) = 0;
49  virtual bool isType(detail::TypeIdHolder::type_id typeId) const = 0;
50 };
51 
52 // Base of object holders, holds a value in the inplace_optional_holder
53 template <typename T, typename ALLOC>
54 class HolderBase : public IHolder<ALLOC>
55 {
56 public:
57  template <typename U>
58  void set(U&& value)
59  {
60  m_typedHolder = std::forward<U>(value);
61  }
62 
63  template <typename U, typename std::enable_if<std::is_constructible<U, NoInitT, U>::value, int>::type = 0>
64  void set(NoInitT, U&& value)
65  {
66  // inplace_optional_holder constructor to prevent it's implicit constructor
67  m_typedHolder.assign(NoInit, inplace_optional_holder<T>(NoInit, std::forward<U>(value)));
68  }
69 
70  template <typename U, typename std::enable_if<!std::is_constructible<U, NoInitT, U>::value, int>::type = 0>
71  void set(NoInitT, U&& value)
72  {
73  m_typedHolder = std::forward<U>(value);
74  }
75 
76  void setHolder(const inplace_optional_holder<T>& value)
77  {
78  m_typedHolder = value;
79  }
80 
81  void setHolder(inplace_optional_holder<T>&& value)
82  {
83  m_typedHolder = std::move(value);
84  }
85 
86  template <typename U, typename std::enable_if<std::is_constructible<U, NoInitT, U>::value, int>::type = 0>
87  void setHolder(NoInitT, const inplace_optional_holder<U>& value)
88  {
89  m_typedHolder.assign(NoInit, value);
90  }
91 
92  template <typename U, typename std::enable_if<std::is_constructible<U, NoInitT, U>::value, int>::type = 0>
93  void setHolder(NoInitT, inplace_optional_holder<U>&& value)
94  {
95  m_typedHolder.assign(NoInit, std::move(value));
96  }
97 
98  template <typename U, typename std::enable_if<!std::is_constructible<U, NoInitT, U>::value, int>::type = 0>
99  void setHolder(NoInitT, const inplace_optional_holder<U>& value)
100  {
101  m_typedHolder = value;
102  }
103 
104  template <typename U, typename std::enable_if<!std::is_constructible<U, NoInitT, U>::value, int>::type = 0>
105  void setHolder(NoInitT, inplace_optional_holder<U>&& value)
106  {
107  m_typedHolder = std::move(value);
108  }
109 
110  T& get()
111  {
112  return m_typedHolder.value();
113  }
114 
115  const T& get() const
116  {
117  return m_typedHolder.value();
118  }
119 
120  bool isType(detail::TypeIdHolder::type_id typeId) const override
121  {
122  return detail::TypeIdHolder::get<T>() == typeId;
123  }
124 
125 protected:
126  inplace_optional_holder<T>& getHolder()
127  {
128  return m_typedHolder;
129  }
130 
131  const inplace_optional_holder<T>& getHolder() const
132  {
133  return m_typedHolder;
134  }
135 
136 private:
137  inplace_optional_holder<T> m_typedHolder;
138 };
139 
140 // Holder allocated on heap
141 template <typename T, typename ALLOC>
142 class HeapHolder : public HolderBase<T, ALLOC>
143 {
144 private:
145  struct ConstructTag
146  {};
147 
148 public:
149  using this_type = HeapHolder<T, ALLOC>;
150 
151  explicit HeapHolder(ConstructTag) noexcept
152  {}
153 
154  static this_type* create(const ALLOC& allocator)
155  {
156  using AllocType = RebindAlloc<ALLOC, this_type>;
157  using AllocTraits = std::allocator_traits<AllocType>;
158 
159  AllocType typedAlloc = allocator;
160  typename AllocTraits::pointer ptr = AllocTraits::allocate(typedAlloc, 1);
161  // this never throws because HeapHolder constructor never throws
162  AllocTraits::construct(typedAlloc, std::addressof(*ptr), ConstructTag{});
163  return ptr;
164  }
165 
166  IHolder<ALLOC>* clone(const ALLOC& allocator) const override
167  {
168  this_type* holder = create(allocator);
169  holder->setHolder(this->getHolder());
170  return holder;
171  }
172 
173  IHolder<ALLOC>* clone(NoInitT, const ALLOC& allocator) const override
174  {
175  this_type* holder = create(allocator);
176  holder->setHolder(NoInit, this->getHolder());
177  return holder;
178  }
179 
180  IHolder<ALLOC>* clone(void*) const override
181  {
182  throw CppRuntimeException("AnyHolder: Unexpected clone call.");
183  }
184 
185  IHolder<ALLOC>* clone(NoInitT, void*) const override
186  {
187  throw CppRuntimeException("AnyHolder: Unexpected clone call.");
188  }
189 
190  IHolder<ALLOC>* move(const ALLOC& allocator) override
191  {
192  this_type* holder = create(allocator);
193  holder->setHolder(std::move(this->getHolder()));
194  return holder;
195  }
196 
197  IHolder<ALLOC>* move(NoInitT, const ALLOC& allocator) override
198  {
199  this_type* holder = create(allocator);
200  holder->setHolder(NoInit, std::move(this->getHolder()));
201  return holder;
202  }
203 
204  IHolder<ALLOC>* move(void*) override
205  {
206  throw CppRuntimeException("AnyHolder: Unexpected move call.");
207  }
208 
209  IHolder<ALLOC>* move(NoInitT, void*) override
210  {
211  throw CppRuntimeException("AnyHolder: Unexpected move call.");
212  }
213 
214  void destroy(const ALLOC& allocator) override
215  {
216  using AllocType = RebindAlloc<ALLOC, this_type>;
217  using AllocTraits = std::allocator_traits<AllocType>;
218 
219  AllocType typedAlloc = allocator;
220  AllocTraits::destroy(typedAlloc, this);
221  AllocTraits::deallocate(typedAlloc, this, 1);
222  }
223 };
224 
225 // Holder allocated in the in-place storage
226 template <typename T, typename ALLOC>
227 class NonHeapHolder : public HolderBase<T, ALLOC>
228 {
229 public:
230  using this_type = NonHeapHolder<T, ALLOC>;
231 
232  static this_type* create(void* storage)
233  {
234  return new (storage) this_type();
235  }
236 
237  IHolder<ALLOC>* clone(const ALLOC&) const override
238  {
239  throw CppRuntimeException("AnyHolder: Unexpected clone call.");
240  }
241 
242  IHolder<ALLOC>* clone(NoInitT, const ALLOC&) const override
243  {
244  throw CppRuntimeException("AnyHolder: Unexpected clone call.");
245  }
246 
247  IHolder<ALLOC>* clone(void* storage) const override
248  {
249  NonHeapHolder* holder = new (storage) NonHeapHolder();
250  holder->setHolder(this->getHolder());
251  return holder;
252  }
253 
254  IHolder<ALLOC>* clone(NoInitT, void* storage) const override
255  {
256  NonHeapHolder* holder = new (storage) NonHeapHolder();
257  holder->setHolder(NoInit, this->getHolder());
258  return holder;
259  }
260 
261  IHolder<ALLOC>* move(const ALLOC&) override
262  {
263  throw CppRuntimeException("AnyHolder: Unexpected move call.");
264  }
265 
266  IHolder<ALLOC>* move(NoInitT, const ALLOC&) override
267  {
268  throw CppRuntimeException("AnyHolder: Unexpected move call.");
269  }
270 
271  IHolder<ALLOC>* move(void* storage) override
272  {
273  NonHeapHolder* holder = new (storage) NonHeapHolder();
274  holder->setHolder(std::move(this->getHolder()));
275  return holder;
276  }
277 
278  IHolder<ALLOC>* move(NoInitT, void* storage) override
279  {
280  NonHeapHolder* holder = new (storage) NonHeapHolder();
281  holder->setHolder(NoInit, std::move(this->getHolder()));
282  return holder;
283  }
284 
285  void destroy(const ALLOC&) override
286  {
287  this->~NonHeapHolder();
288  }
289 
290 private:
291  NonHeapHolder() = default;
292 };
293 
294 template <typename ALLOC>
295 union UntypedHolder
296 {
297  // 2 * sizeof(void*) for T + sizeof(void*) for Holder's vptr
298  using MaxInPlaceType = std::aligned_storage<3 * sizeof(void*), alignof(void*)>::type;
299 
300  detail::IHolder<ALLOC>* heap;
301  MaxInPlaceType inPlace;
302 };
303 
304 template <typename T, typename ALLOC>
305 using has_non_heap_holder = std::integral_constant<bool,
306  sizeof(NonHeapHolder<T, ALLOC>) <= sizeof(typename UntypedHolder<ALLOC>::MaxInPlaceType) &&
307  std::is_nothrow_move_constructible<T>::value &&
308  alignof(T) <= alignof(typename UntypedHolder<ALLOC>::MaxInPlaceType)>;
309 
310 } // namespace detail
311 
315 template <typename ALLOC = std::allocator<uint8_t>>
316 class AnyHolder : public AllocatorHolder<ALLOC>
317 {
318  using AllocTraits = std::allocator_traits<ALLOC>;
321 
322 public:
324  using allocator_type = ALLOC;
325 
330  AnyHolder(ALLOC())
331  {}
332 
336  explicit AnyHolder(const ALLOC& allocator) :
337  AllocatorHolder<ALLOC>(allocator)
338  {
339  m_untypedHolder.heap = nullptr;
340  }
341 
347  template <typename T,
348  typename std::enable_if<!std::is_same<typename std::decay<T>::type, AnyHolder>::value &&
349  !std::is_same<typename std::decay<T>::type, ALLOC>::value,
350  int>::type = 0>
351  explicit AnyHolder(T&& value, const ALLOC& allocator = ALLOC()) :
352  AllocatorHolder<ALLOC>(allocator)
353  {
354  m_untypedHolder.heap = nullptr;
355  set(std::forward<T>(value));
356  }
357 
363  template <typename T,
364  typename std::enable_if<!std::is_same<typename std::decay<T>::type, AnyHolder>::value, int>::type =
365  0>
366  explicit AnyHolder(NoInitT, T&& value, const ALLOC& allocator = ALLOC()) :
367  AllocatorHolder<ALLOC>(allocator)
368  {
369  m_untypedHolder.heap = nullptr;
370  set(NoInit, std::forward<T>(value));
371  }
372 
377  {
378  clearHolder();
379  }
380 
386  AnyHolder(const AnyHolder& other) :
387  AllocatorHolder<ALLOC>(
388  AllocTraits::select_on_container_copy_construction(other.get_allocator_ref()))
389  {
390  copy(other);
391  }
392 
398  AnyHolder(NoInitT, const AnyHolder& other) :
399  AllocatorHolder<ALLOC>(
400  AllocTraits::select_on_container_copy_construction(other.get_allocator_ref()))
401  {
402  copy(NoInit, other);
403  }
404 
411  AnyHolder(const AnyHolder& other, const ALLOC& allocator) :
412  AllocatorHolder<ALLOC>(allocator)
413  {
414  copy(other);
415  }
416 
423  AnyHolder(NoInitT, const AnyHolder& other, const ALLOC& allocator) :
424  AllocatorHolder<ALLOC>(allocator)
425  {
426  copy(NoInit, other);
427  }
428 
437  {
438  if (this != &other)
439  {
440  // TODO: do not dealloc unless necessary
441  clearHolder();
442  if (AllocTraits::propagate_on_container_copy_assignment::value)
443  {
445  }
446  copy(other);
447  }
448 
449  return *this;
450  }
451 
460  {
461  if (this != &other)
462  {
463  // TODO: do not dealloc unless necessary
464  clearHolder();
465  if (AllocTraits::propagate_on_container_copy_assignment::value)
466  {
468  }
469  copy(NoInit, other);
470  }
471 
472  return *this;
473  }
474 
480  AnyHolder(AnyHolder&& other) noexcept :
481  AllocatorHolder<ALLOC>(std::move(other.get_allocator_ref()))
482  {
483  move(std::move(other));
484  }
485 
491  AnyHolder(NoInitT, AnyHolder&& other) noexcept :
492  AllocatorHolder<ALLOC>(std::move(other.get_allocator_ref()))
493  {
494  move(NoInit, std::move(other));
495  }
496 
503  AnyHolder(AnyHolder&& other, const ALLOC& allocator) :
504  AllocatorHolder<ALLOC>(allocator)
505  {
506  move(std::move(other));
507  }
508 
515  AnyHolder(NoInitT, AnyHolder&& other, const ALLOC& allocator) :
516  AllocatorHolder<ALLOC>(allocator)
517  {
518  move(NoInit, std::move(other));
519  }
520 
529  {
530  if (this != &other)
531  {
532  clearHolder();
533  if (AllocTraits::propagate_on_container_move_assignment::value)
534  {
535  set_allocator(std::move(other.get_allocator_ref()));
536  }
537  move(std::move(other));
538  }
539 
540  return *this;
541  }
542 
551  {
552  if (this != &other)
553  {
554  clearHolder();
555  if (AllocTraits::propagate_on_container_move_assignment::value)
556  {
557  set_allocator(std::move(other.get_allocator_ref()));
558  }
559  move(NoInit, std::move(other));
560  }
561 
562  return *this;
563  }
564 
572  template <typename T,
573  typename std::enable_if<!std::is_same<typename std::decay<T>::type, AnyHolder>::value, int>::type =
574  0>
575  AnyHolder& operator=(T&& value)
576  {
577  set(std::forward<T>(value));
578 
579  return *this;
580  }
581 
585  void reset()
586  {
587  clearHolder();
588  }
589 
595  template <typename T>
596  void set(T&& value)
597  {
598  createHolder<typename std::decay<T>::type>()->set(std::forward<T>(value));
599  }
600 
606  template <typename T>
607  void set(NoInitT, T&& value)
608  {
609  createHolder<typename std::decay<T>::type>()->set(NoInit, std::forward<T>(value));
610  }
611 
619  template <typename T>
620  T& get()
621  {
622  checkType<T>();
623  return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>())->get();
624  }
625 
633  template <typename T>
634  const T& get() const
635  {
636  checkType<T>();
637  return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>())->get();
638  }
639 
645  template <typename T>
646  bool isType() const
647  {
648  return hasHolder() && getUntypedHolder()->isType(detail::TypeIdHolder::get<T>());
649  }
650 
656  bool hasValue() const
657  {
658  return hasHolder();
659  }
660 
661 private:
662  void copy(const AnyHolder& other)
663  {
664  if (other.m_isInPlace)
665  {
666  other.getUntypedHolder()->clone(&m_untypedHolder.inPlace);
667  m_isInPlace = true;
668  }
669  else if (other.m_untypedHolder.heap != nullptr)
670  {
671  m_untypedHolder.heap = other.getUntypedHolder()->clone(get_allocator_ref());
672  }
673  else
674  {
675  m_untypedHolder.heap = nullptr;
676  }
677  }
678 
679  void copy(NoInitT, const AnyHolder& other)
680  {
681  if (other.m_isInPlace)
682  {
683  other.getUntypedHolder()->clone(NoInit, &m_untypedHolder.inPlace);
684  m_isInPlace = true;
685  }
686  else if (other.m_untypedHolder.heap != nullptr)
687  {
688  m_untypedHolder.heap = other.getUntypedHolder()->clone(NoInit, get_allocator_ref());
689  }
690  else
691  {
692  m_untypedHolder.heap = nullptr;
693  }
694  }
695 
696  void move(AnyHolder&& other)
697  {
698  if (other.m_isInPlace)
699  {
700  other.getUntypedHolder()->move(&m_untypedHolder.inPlace);
701  m_isInPlace = true;
702  other.clearHolder();
703  }
704  else if (other.m_untypedHolder.heap != nullptr)
705  {
706  if (get_allocator_ref() == other.get_allocator_ref())
707  {
708  // take over the other's storage
709  m_untypedHolder.heap = other.m_untypedHolder.heap;
710  other.m_untypedHolder.heap = nullptr;
711  }
712  else
713  {
714  // cannot steal the storage, allocate our own and move the holder
715  m_untypedHolder.heap = other.getUntypedHolder()->move(get_allocator_ref());
716  other.clearHolder();
717  }
718  }
719  else
720  {
721  m_untypedHolder.heap = nullptr;
722  }
723  }
724 
725  void move(NoInitT, AnyHolder&& other)
726  {
727  if (other.m_isInPlace)
728  {
729  other.getUntypedHolder()->move(NoInit, &m_untypedHolder.inPlace);
730  m_isInPlace = true;
731  other.clearHolder();
732  }
733  else if (other.m_untypedHolder.heap != nullptr)
734  {
735  if (get_allocator_ref() == other.get_allocator_ref())
736  {
737  // take over the other's storage
738  m_untypedHolder.heap = other.m_untypedHolder.heap;
739  other.m_untypedHolder.heap = nullptr;
740  }
741  else
742  {
743  // cannot steal the storage, allocate our own and move the holder
744  m_untypedHolder.heap = other.getUntypedHolder()->move(NoInit, get_allocator_ref());
745  other.clearHolder();
746  }
747  }
748  else
749  {
750  m_untypedHolder.heap = nullptr;
751  }
752  }
753 
754  void clearHolder()
755  {
756  if (hasHolder())
757  {
758  getUntypedHolder()->destroy(get_allocator_ref());
759  m_isInPlace = false;
760  m_untypedHolder.heap = nullptr;
761  }
762  }
763 
764  bool hasHolder() const
765  {
766  return (m_isInPlace || m_untypedHolder.heap != nullptr);
767  }
768 
769  template <typename T>
770  detail::HolderBase<T, ALLOC>* createHolder()
771  {
772  if (hasHolder())
773  {
774  if (getUntypedHolder()->isType(detail::TypeIdHolder::get<T>()))
775  {
776  return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>());
777  }
778 
779  clearHolder();
780  }
781 
782  return createHolderImpl<T>(detail::has_non_heap_holder<T, ALLOC>());
783  }
784 
785  template <typename T>
786  detail::HolderBase<T, ALLOC>* createHolderImpl(std::true_type)
787  {
788  detail::NonHeapHolder<T, ALLOC>* holder =
789  detail::NonHeapHolder<T, ALLOC>::create(&m_untypedHolder.inPlace);
790  m_isInPlace = true;
791  return holder;
792  }
793 
794  template <typename T>
795  detail::HolderBase<T, ALLOC>* createHolderImpl(std::false_type)
796  {
797  detail::HeapHolder<T, ALLOC>* holder = detail::HeapHolder<T, ALLOC>::create(get_allocator_ref());
798  m_untypedHolder.heap = holder;
799  return holder;
800  }
801 
802  template <typename T>
803  void checkType() const
804  {
805  if (!isType<T>())
806  {
807  throwBadType();
808  }
809  }
810 
812  void throwBadType() const
813  {
814  throw CppRuntimeException("Bad type in AnyHolder");
815  }
816 
817  template <typename T>
818  detail::HeapHolder<T, ALLOC>* getHeapHolder()
819  {
820  return static_cast<detail::HeapHolder<T, ALLOC>*>(m_untypedHolder.heap);
821  }
822 
823  template <typename T>
824  const detail::HeapHolder<T, ALLOC>* getHeapHolder() const
825  {
826  return static_cast<detail::HeapHolder<T, ALLOC>*>(m_untypedHolder.heap);
827  }
828 
829  template <typename T>
830  detail::NonHeapHolder<T, ALLOC>* getInplaceHolder()
831  {
832  return reinterpret_cast<detail::NonHeapHolder<T, ALLOC>*>(&m_untypedHolder.inPlace);
833  }
834 
835  template <typename T>
836  const detail::NonHeapHolder<T, ALLOC>* getInplaceHolder() const
837  {
838  return reinterpret_cast<const detail::NonHeapHolder<T, ALLOC>*>(&m_untypedHolder.inPlace);
839  }
840 
841  template <typename T>
842  detail::HolderBase<T, ALLOC>* getHolder(std::true_type)
843  {
844  return static_cast<detail::HolderBase<T, ALLOC>*>(getInplaceHolder<T>());
845  }
846 
847  template <typename T>
848  detail::HolderBase<T, ALLOC>* getHolder(std::false_type)
849  {
850  return static_cast<detail::HolderBase<T, ALLOC>*>(getHeapHolder<T>());
851  }
852 
853  template <typename T>
854  const detail::HolderBase<T, ALLOC>* getHolder(std::true_type) const
855  {
856  return static_cast<const detail::HolderBase<T, ALLOC>*>(getInplaceHolder<T>());
857  }
858 
859  template <typename T>
860  const detail::HolderBase<T, ALLOC>* getHolder(std::false_type) const
861  {
862  return static_cast<const detail::HolderBase<T, ALLOC>*>(getHeapHolder<T>());
863  }
864 
865  detail::IHolder<ALLOC>* getUntypedHolder()
866  {
867  return (m_isInPlace)
868  ? reinterpret_cast<detail::IHolder<ALLOC>*>(&m_untypedHolder.inPlace)
869  : m_untypedHolder.heap;
870  }
871 
872  const detail::IHolder<ALLOC>* getUntypedHolder() const
873  {
874  return (m_isInPlace)
875  ? reinterpret_cast<const detail::IHolder<ALLOC>*>(&m_untypedHolder.inPlace)
876  : m_untypedHolder.heap;
877  }
878 
879  detail::UntypedHolder<ALLOC> m_untypedHolder;
880  bool m_isInPlace = false;
881 };
882 
883 } // namespace zserio
884 
885 #endif // ifndef ZSERIO_ANY_HOLDER_H_INC
void set_allocator(const allocator_type &allocator)
ALLOC allocator_type
Definition: AnyHolder.h:324
AnyHolder(NoInitT, T &&value, const ALLOC &allocator=ALLOC())
Definition: AnyHolder.h:366
AnyHolder(const AnyHolder &other, const ALLOC &allocator)
Definition: AnyHolder.h:411
AnyHolder(NoInitT, AnyHolder &&other, const ALLOC &allocator)
Definition: AnyHolder.h:515
bool isType() const
Definition: AnyHolder.h:646
AnyHolder(AnyHolder &&other, const ALLOC &allocator)
Definition: AnyHolder.h:503
void set(T &&value)
Definition: AnyHolder.h:596
AnyHolder(const ALLOC &allocator)
Definition: AnyHolder.h:336
AnyHolder(NoInitT, AnyHolder &&other) noexcept
Definition: AnyHolder.h:491
AnyHolder(AnyHolder &&other) noexcept
Definition: AnyHolder.h:480
AnyHolder & operator=(T &&value)
Definition: AnyHolder.h:575
AnyHolder(NoInitT, const AnyHolder &other, const ALLOC &allocator)
Definition: AnyHolder.h:423
bool hasValue() const
Definition: AnyHolder.h:656
AnyHolder & operator=(const AnyHolder &other)
Definition: AnyHolder.h:436
AnyHolder(const AnyHolder &other)
Definition: AnyHolder.h:386
AnyHolder & operator=(AnyHolder &&other)
Definition: AnyHolder.h:528
AnyHolder & assign(NoInitT, AnyHolder &&other)
Definition: AnyHolder.h:550
AnyHolder(NoInitT, const AnyHolder &other)
Definition: AnyHolder.h:398
void set(NoInitT, T &&value)
Definition: AnyHolder.h:607
const T & get() const
Definition: AnyHolder.h:634
AnyHolder(T &&value, const ALLOC &allocator=ALLOC())
Definition: AnyHolder.h:351
AnyHolder & assign(NoInitT, const AnyHolder &other)
Definition: AnyHolder.h:459
std::set< T, COMPARE, PropagatingPolymorphicAllocator< T > > set
Definition: Set.h:17
constexpr NoInitT NoInit
Definition: NoInit.h:18