44 static constexpr auto NumTypes = Union::FieldsTypes::size;
48 type = TypeAt<0>::value;
49 new (&fieldAt<0>(), PlacementNew())
typename TypeAt<0>::type();
60 visit(CopyConstruct(), other);
68 visit(MoveConstruct(), other);
75 if (type == other.type)
77 visit<CopyAssign>(other);
83 visit(CopyConstruct(), other);
92 if (type == other.type)
94 visit(MoveAssign(), other);
100 visit(MoveConstruct(), other);
108 template <EnumType wantedEnum,
int StartIndex = NumTypes>
111 static constexpr int index = wantedEnum == TypeAt<StartIndex - 1>::value
113 : EnumToType<wantedEnum, StartIndex - 1>::index;
114 static_assert(index >= 0,
"Type not found!");
116 typename TypeAt<StartIndex - 1>::type,
117 typename EnumToType<wantedEnum, StartIndex - 1>::type>;
120 template <EnumType wantedEnum>
121 struct EnumToType<wantedEnum, 0>
123 using type =
typename TypeAt<0>::type;
124 static constexpr int index = 0;
142 bool operator==(
const TaggedUnion& other)
const {
return type == other.type and visit<Equals>(other); }
148 template <EnumType wantedType,
typename U>
151 auto&
field = fieldAt<EnumToType<wantedType>::index>();
152 if (type == wantedType)
158 using T =
typename EnumToType<wantedType>::type;
170 template <EnumType wantedType>
171 typename TypeAt<EnumToType<wantedType>::index>::type&
changeTo()
173 using T =
typename EnumToType<wantedType>::type;
174 auto&
field = fieldAt<EnumToType<wantedType>::index>();
175 if (type != wantedType)
179 new (&
field, PlacementNew()) T();
188 template <EnumType wantedType>
189 [[nodiscard]]
typename TypeAt<EnumToType<wantedType>::index>::type*
field()
191 if (wantedType == type)
193 return &fieldAt<EnumToType<wantedType>::index>();
202 template <EnumType wantedType>
203 [[nodiscard]]
const typename TypeAt<EnumToType<wantedType>::index>::type*
field()
const
205 if (wantedType == type)
207 return &fieldAt<EnumToType<wantedType>::index>();
218 using T =
typename TypeAt<Index>::type;
219 t1.fieldAt<Index>().~T();
226 void operator()(TaggedUnion& t1)
228 using T =
typename TypeAt<Index>::type;
229 new (&t1.fieldAt<Index>(), PlacementNew()) T();
236 void operator()(TaggedUnion& t1,
const TaggedUnion& t2)
238 using T =
typename TypeAt<Index>::type;
239 new (&t1.fieldAt<Index>(), PlacementNew()) T(t2.fieldAt<Index>());
246 void operator()(TaggedUnion& t1, TaggedUnion& t2)
248 using T =
typename TypeAt<Index>::type;
249 new (&t1.fieldAt<Index>(), PlacementNew()) T(
move(t2.fieldAt<Index>()));
256 void operator()(TaggedUnion& t1,
const TaggedUnion& t2)
258 t1.fieldAt<Index>() = t2.fieldAt<Index>();
265 void operator()(TaggedUnion& t1, TaggedUnion& t2)
267 t1.fieldAt<Index>() =
move(t2.fieldAt<Index>());
274 static auto visit(TaggedUnion& t1, TaggedUnion& t2)
276 return t1.fieldAt<Index>() ==
move(t2.fieldAt<Index>());
280 template <
typename Visitor,
typename... Arguments>
281 auto visit(Visitor&& visitor, Arguments&&... args)
286 template <
typename Visitor,
size_t StartIndex = NumTypes>
287 struct RuntimeEnumVisit
289 static constexpr auto Index = StartIndex - 1;
291 template <
typename... Args>
292 static auto visit(Visitor&& visitor, EnumType enumType, Args&... args)
294 if (enumType == TypeAt<Index>::value)
296 return visitor.template operator()<Index>(args...);
300 return RuntimeEnumVisit<Visitor, Index>::visit(
forward<Visitor>(visitor), enumType, args...);
305 template <
typename Visitor>
306 struct RuntimeEnumVisit<Visitor, 0>
308 template <
typename... Args>
309 static auto visit(Visitor&& visitor, EnumType, Args&... args)
311 return visitor.template operator()<0>(args...);
316 [[nodiscard]]
auto& fieldAt()
318 using T =
typename TypeAt<index>::type;
319 return storage.template reinterpret_as<T>();
323 [[nodiscard]]
const auto& fieldAt()
const
325 using T =
typename TypeAt<index>::type;
326 return storage.template reinterpret_as<const T>();
329 template <
class ForwardIt>
330 static constexpr ForwardIt MaxElement(ForwardIt first, ForwardIt last)
334 ForwardIt largest = first;
335 for (++first; first != last; ++first)
337 if (*largest < *first)
345 static constexpr T MaxElement(std::initializer_list<T> list)
347 return *MaxElement(list.begin(), list.end());
350 template <
class... Types>
351 struct ComputeMaxSizeAndAlignment;
353 template <
class... Types>
354 struct ComputeMaxSizeAndAlignment<TypeTraits::TypeList<Types...>>
356 static constexpr size_t maxAlignment = MaxElement({
alignof(
typename Types::type)...});
357 static constexpr size_t maxSize = MaxElement({
sizeof(
typename Types::type)...});
360 using Storage = ComputeMaxSizeAndAlignment<typename Union::FieldsTypes>;
362 AlignedStorage<Storage::maxSize, Storage::maxAlignment> storage;
typename Conditional< B, T, F >::type ConditionalT
ConditionalT is an alias template that resolves to type T if a boolean value is true,...
Definition TypeTraits.h:70