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