Zserio C++ runtime library  1.0.1
Built for Zserio 2.14.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)
445  copy(other);
446  }
447 
448  return *this;
449  }
450 
459  {
460  if (this != &other)
461  {
462  // TODO: do not dealloc unless necessary
463  clearHolder();
464  if (AllocTraits::propagate_on_container_copy_assignment::value)
466  copy(NoInit, other);
467  }
468 
469  return *this;
470  }
471 
477  AnyHolder(AnyHolder&& other) noexcept :
478  AllocatorHolder<ALLOC>(std::move(other.get_allocator_ref()))
479  {
480  move(std::move(other));
481  }
482 
488  AnyHolder(NoInitT, AnyHolder&& other) noexcept :
489  AllocatorHolder<ALLOC>(std::move(other.get_allocator_ref()))
490  {
491  move(NoInit, std::move(other));
492  }
493 
500  AnyHolder(AnyHolder&& other, const ALLOC& allocator) :
501  AllocatorHolder<ALLOC>(allocator)
502  {
503  move(std::move(other));
504  }
505 
512  AnyHolder(NoInitT, AnyHolder&& other, const ALLOC& allocator) :
513  AllocatorHolder<ALLOC>(allocator)
514  {
515  move(NoInit, std::move(other));
516  }
517 
526  {
527  if (this != &other)
528  {
529  clearHolder();
530  if (AllocTraits::propagate_on_container_move_assignment::value)
531  set_allocator(std::move(other.get_allocator_ref()));
532  move(std::move(other));
533  }
534 
535  return *this;
536  }
537 
546  {
547  if (this != &other)
548  {
549  clearHolder();
550  if (AllocTraits::propagate_on_container_move_assignment::value)
551  set_allocator(std::move(other.get_allocator_ref()));
552  move(NoInit, std::move(other));
553  }
554 
555  return *this;
556  }
557 
565  template <typename T,
566  typename std::enable_if<!std::is_same<typename std::decay<T>::type, AnyHolder>::value, int>::type =
567  0>
568  AnyHolder& operator=(T&& value)
569  {
570  set(std::forward<T>(value));
571 
572  return *this;
573  }
574 
578  void reset()
579  {
580  clearHolder();
581  }
582 
588  template <typename T>
589  void set(T&& value)
590  {
591  createHolder<typename std::decay<T>::type>()->set(std::forward<T>(value));
592  }
593 
599  template <typename T>
600  void set(NoInitT, T&& value)
601  {
602  createHolder<typename std::decay<T>::type>()->set(NoInit, std::forward<T>(value));
603  }
604 
612  template <typename T>
613  T& get()
614  {
615  checkType<T>();
616  return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>())->get();
617  }
618 
626  template <typename T>
627  const T& get() const
628  {
629  checkType<T>();
630  return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>())->get();
631  }
632 
638  template <typename T>
639  bool isType() const
640  {
641  return hasHolder() && getUntypedHolder()->isType(detail::TypeIdHolder::get<T>());
642  }
643 
649  bool hasValue() const
650  {
651  return hasHolder();
652  }
653 
654 private:
655  void copy(const AnyHolder& other)
656  {
657  if (other.m_isInPlace)
658  {
659  other.getUntypedHolder()->clone(&m_untypedHolder.inPlace);
660  m_isInPlace = true;
661  }
662  else if (other.m_untypedHolder.heap != nullptr)
663  {
664  m_untypedHolder.heap = other.getUntypedHolder()->clone(get_allocator_ref());
665  }
666  else
667  {
668  m_untypedHolder.heap = nullptr;
669  }
670  }
671 
672  void copy(NoInitT, const AnyHolder& other)
673  {
674  if (other.m_isInPlace)
675  {
676  other.getUntypedHolder()->clone(NoInit, &m_untypedHolder.inPlace);
677  m_isInPlace = true;
678  }
679  else if (other.m_untypedHolder.heap != nullptr)
680  {
681  m_untypedHolder.heap = other.getUntypedHolder()->clone(NoInit, get_allocator_ref());
682  }
683  else
684  {
685  m_untypedHolder.heap = nullptr;
686  }
687  }
688 
689  void move(AnyHolder&& other)
690  {
691  if (other.m_isInPlace)
692  {
693  other.getUntypedHolder()->move(&m_untypedHolder.inPlace);
694  m_isInPlace = true;
695  other.clearHolder();
696  }
697  else if (other.m_untypedHolder.heap != nullptr)
698  {
699  if (get_allocator_ref() == other.get_allocator_ref())
700  {
701  // take over the other's storage
702  m_untypedHolder.heap = other.m_untypedHolder.heap;
703  other.m_untypedHolder.heap = nullptr;
704  }
705  else
706  {
707  // cannot steal the storage, allocate our own and move the holder
708  m_untypedHolder.heap = other.getUntypedHolder()->move(get_allocator_ref());
709  other.clearHolder();
710  }
711  }
712  else
713  {
714  m_untypedHolder.heap = nullptr;
715  }
716  }
717 
718  void move(NoInitT, AnyHolder&& other)
719  {
720  if (other.m_isInPlace)
721  {
722  other.getUntypedHolder()->move(NoInit, &m_untypedHolder.inPlace);
723  m_isInPlace = true;
724  other.clearHolder();
725  }
726  else if (other.m_untypedHolder.heap != nullptr)
727  {
728  if (get_allocator_ref() == other.get_allocator_ref())
729  {
730  // take over the other's storage
731  m_untypedHolder.heap = other.m_untypedHolder.heap;
732  other.m_untypedHolder.heap = nullptr;
733  }
734  else
735  {
736  // cannot steal the storage, allocate our own and move the holder
737  m_untypedHolder.heap = other.getUntypedHolder()->move(NoInit, get_allocator_ref());
738  other.clearHolder();
739  }
740  }
741  else
742  {
743  m_untypedHolder.heap = nullptr;
744  }
745  }
746 
747  void clearHolder()
748  {
749  if (hasHolder())
750  {
751  getUntypedHolder()->destroy(get_allocator_ref());
752  m_isInPlace = false;
753  m_untypedHolder.heap = nullptr;
754  }
755  }
756 
757  bool hasHolder() const
758  {
759  return (m_isInPlace || m_untypedHolder.heap != nullptr);
760  }
761 
762  template <typename T>
763  detail::HolderBase<T, ALLOC>* createHolder()
764  {
765  if (hasHolder())
766  {
767  if (getUntypedHolder()->isType(detail::TypeIdHolder::get<T>()))
768  return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>());
769 
770  clearHolder();
771  }
772 
773  return createHolderImpl<T>(detail::has_non_heap_holder<T, ALLOC>());
774  }
775 
776  template <typename T>
777  detail::HolderBase<T, ALLOC>* createHolderImpl(std::true_type)
778  {
779  detail::NonHeapHolder<T, ALLOC>* holder =
780  detail::NonHeapHolder<T, ALLOC>::create(&m_untypedHolder.inPlace);
781  m_isInPlace = true;
782  return holder;
783  }
784 
785  template <typename T>
786  detail::HolderBase<T, ALLOC>* createHolderImpl(std::false_type)
787  {
788  detail::HeapHolder<T, ALLOC>* holder = detail::HeapHolder<T, ALLOC>::create(get_allocator_ref());
789  m_untypedHolder.heap = holder;
790  return holder;
791  }
792 
793  template <typename T>
794  void checkType() const
795  {
796  if (!isType<T>())
797  throwBadType();
798  }
799 
801  void throwBadType() const
802  {
803  throw CppRuntimeException("Bad type in AnyHolder");
804  }
805 
806  template <typename T>
807  detail::HeapHolder<T, ALLOC>* getHeapHolder()
808  {
809  return static_cast<detail::HeapHolder<T, ALLOC>*>(m_untypedHolder.heap);
810  }
811 
812  template <typename T>
813  const detail::HeapHolder<T, ALLOC>* getHeapHolder() const
814  {
815  return static_cast<detail::HeapHolder<T, ALLOC>*>(m_untypedHolder.heap);
816  }
817 
818  template <typename T>
819  detail::NonHeapHolder<T, ALLOC>* getInplaceHolder()
820  {
821  return reinterpret_cast<detail::NonHeapHolder<T, ALLOC>*>(&m_untypedHolder.inPlace);
822  }
823 
824  template <typename T>
825  const detail::NonHeapHolder<T, ALLOC>* getInplaceHolder() const
826  {
827  return reinterpret_cast<const detail::NonHeapHolder<T, ALLOC>*>(&m_untypedHolder.inPlace);
828  }
829 
830  template <typename T>
831  detail::HolderBase<T, ALLOC>* getHolder(std::true_type)
832  {
833  return static_cast<detail::HolderBase<T, ALLOC>*>(getInplaceHolder<T>());
834  }
835 
836  template <typename T>
837  detail::HolderBase<T, ALLOC>* getHolder(std::false_type)
838  {
839  return static_cast<detail::HolderBase<T, ALLOC>*>(getHeapHolder<T>());
840  }
841 
842  template <typename T>
843  const detail::HolderBase<T, ALLOC>* getHolder(std::true_type) const
844  {
845  return static_cast<const detail::HolderBase<T, ALLOC>*>(getInplaceHolder<T>());
846  }
847 
848  template <typename T>
849  const detail::HolderBase<T, ALLOC>* getHolder(std::false_type) const
850  {
851  return static_cast<const detail::HolderBase<T, ALLOC>*>(getHeapHolder<T>());
852  }
853 
854  detail::IHolder<ALLOC>* getUntypedHolder()
855  {
856  return (m_isInPlace)
857  ? reinterpret_cast<detail::IHolder<ALLOC>*>(&m_untypedHolder.inPlace)
858  : m_untypedHolder.heap;
859  }
860 
861  const detail::IHolder<ALLOC>* getUntypedHolder() const
862  {
863  return (m_isInPlace)
864  ? reinterpret_cast<const detail::IHolder<ALLOC>*>(&m_untypedHolder.inPlace)
865  : m_untypedHolder.heap;
866  }
867 
868  detail::UntypedHolder<ALLOC> m_untypedHolder;
869  bool m_isInPlace = false;
870 };
871 
872 } // namespace zserio
873 
874 #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:512
bool isType() const
Definition: AnyHolder.h:639
AnyHolder(AnyHolder &&other, const ALLOC &allocator)
Definition: AnyHolder.h:500
void set(T &&value)
Definition: AnyHolder.h:589
AnyHolder(const ALLOC &allocator)
Definition: AnyHolder.h:337
AnyHolder(NoInitT, AnyHolder &&other) noexcept
Definition: AnyHolder.h:488
AnyHolder(AnyHolder &&other) noexcept
Definition: AnyHolder.h:477
AnyHolder & operator=(T &&value)
Definition: AnyHolder.h:568
AnyHolder(NoInitT, const AnyHolder &other, const ALLOC &allocator)
Definition: AnyHolder.h:424
bool hasValue() const
Definition: AnyHolder.h:649
AnyHolder & operator=(const AnyHolder &other)
Definition: AnyHolder.h:437
AnyHolder(const AnyHolder &other)
Definition: AnyHolder.h:387
AnyHolder & operator=(AnyHolder &&other)
Definition: AnyHolder.h:525
AnyHolder & assign(NoInitT, AnyHolder &&other)
Definition: AnyHolder.h:545
AnyHolder(NoInitT, const AnyHolder &other)
Definition: AnyHolder.h:399
void set(NoInitT, T &&value)
Definition: AnyHolder.h:600
const T & get() const
Definition: AnyHolder.h:627
AnyHolder(T &&value, const ALLOC &allocator=ALLOC())
Definition: AnyHolder.h:352
AnyHolder & assign(NoInitT, const AnyHolder &other)
Definition: AnyHolder.h:458
std::set< T, COMPARE, PropagatingPolymorphicAllocator< T > > set
Definition: Set.h:17
constexpr NoInitT NoInit
Definition: NoInit.h:18