19 #if !defined(VISKORES_DEVICE) || !defined(VISKORES_NAMESPACE)
20 #error VariantImpl.h must be included from Variant.h
22 #define VISKORES_DEVICE
23 #define VISKORES_NAMESPACE tmp
38 template <
typename... Ts>
47 template <
typename UnionType>
48 struct VariantUnionToListImpl;
49 template <
typename... Ts>
50 struct VariantUnionToListImpl<detail::VariantUnionTD<Ts...>>
54 template <
typename... Ts>
55 struct VariantUnionToListImpl<detail::VariantUnionNTD<Ts...>>
60 template <
typename UnionType>
61 using VariantUnionToList =
62 typename VariantUnionToListImpl<typename std::decay<UnionType>::type>::type;
64 struct VariantCopyConstructFunctor
66 template <
typename T,
typename UnionType>
67 VISKORES_DEVICE void operator()(
const T& src, UnionType& destUnion)
const noexcept
72 new (&VariantUnionGet<Index>(destUnion)) T(src);
76 struct VariantCopyFunctor
78 template <
typename T,
typename UnionType>
79 VISKORES_DEVICE void operator()(
const T& src, UnionType& destUnion)
const noexcept
85 src, VariantUnionGet<Index>(destUnion),
typename std::is_copy_assignable<T>::type{});
89 VISKORES_DEVICE void DoCopy(
const T& src, T& dest, std::true_type)
const noexcept
95 VISKORES_DEVICE void DoCopy(
const T& src, T& dest, std::false_type)
const noexcept
110 struct VariantDestroyFunctor
112 template <
typename T>
119 template <
typename T>
120 struct VariantCheckType
128 "References are not allowed in Viskores Variant.");
130 "Pointers are not allowed in Viskores Variant.");
133 template <
typename VariantType>
134 struct VariantTriviallyCopyable;
136 template <
typename... Ts>
137 struct VariantTriviallyCopyable<
viskores::VISKORES_NAMESPACE::Variant<Ts...>>
138 : AllTriviallyCopyable<Ts...>
142 template <
typename VariantType>
143 struct VariantTriviallyConstructible;
145 template <
typename... Ts>
146 struct VariantTriviallyConstructible<
viskores::VISKORES_NAMESPACE::Variant<Ts...>>
147 : AllTriviallyConstructible<Ts...>
153 template <
typename... Ts>
154 struct VariantStorageImpl
156 VariantUnion<Ts...> Storage;
159 VariantStorageImpl() =
default;
166 template <viskores::IdComponent Index>
172 return (this->Index >= 0) && (this->Index < static_cast<viskores::IdComponent>(
sizeof...(Ts)));
179 this->
CastAndCall(detail::VariantDestroyFunctor{});
184 template <
typename Functor,
typename... Args>
186 noexcept(noexcept(f(std::declval<
const TypeAt<0>&>(), args...)))
187 -> decltype(f(std::declval<
const TypeAt<0>&>(), args...))
190 return detail::VariantCastAndCallImpl<
sizeof...(Ts)>(
191 this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
194 template <
typename Functor,
typename... Args>
196 noexcept(f(std::declval<
const TypeAt<0>&>(), args...)))
197 -> decltype(f(std::declval<TypeAt<0>&>(), args...))
200 return detail::VariantCastAndCallImpl<
sizeof...(Ts)>(
201 this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
208 template <
typename VariantType,
209 typename TriviallyConstructible =
210 typename VariantTriviallyConstructible<VariantType>::type,
211 typename TriviallyCopyable =
typename VariantTriviallyCopyable<VariantType>::type>
212 struct VariantConstructorImpl;
215 template <
typename... Ts>
216 struct VariantConstructorImpl<
viskores::VISKORES_NAMESPACE::Variant<Ts...>,
218 std::true_type> : VariantStorageImpl<Ts...>
220 VariantConstructorImpl() =
default;
221 ~VariantConstructorImpl() =
default;
223 VariantConstructorImpl(
const VariantConstructorImpl&) =
default;
224 VariantConstructorImpl(VariantConstructorImpl&&) =
default;
225 VariantConstructorImpl& operator=(
const VariantConstructorImpl&) =
default;
226 VariantConstructorImpl& operator=(VariantConstructorImpl&&) =
default;
231 template <
typename... Ts>
232 struct VariantConstructorImpl<
viskores::VISKORES_NAMESPACE::Variant<Ts...>,
234 std::true_type> : VariantStorageImpl<Ts...>
237 : VariantStorageImpl<Ts...>(
viskores::internal::NullType{})
243 ~VariantConstructorImpl() =
default;
245 VariantConstructorImpl(
const VariantConstructorImpl&) =
default;
246 VariantConstructorImpl(VariantConstructorImpl&&) =
default;
247 VariantConstructorImpl& operator=(
const VariantConstructorImpl&) =
default;
248 VariantConstructorImpl& operator=(VariantConstructorImpl&&) =
default;
252 template <
typename construct_type,
typename... Ts>
253 struct VariantConstructorImpl<
viskores::VISKORES_NAMESPACE::Variant<Ts...>,
255 std::false_type> : VariantStorageImpl<Ts...>
258 : VariantStorageImpl<Ts...>(
viskores::internal::NullType{})
264 VISKORES_DEVICE VariantConstructorImpl(
const VariantConstructorImpl& src) noexcept
265 : VariantStorageImpl<Ts...>(viskores::internal::NullType{})
269 src.CastAndCall(VariantCopyConstructFunctor{}, this->Storage);
271 this->Index = src.Index;
274 VISKORES_DEVICE VariantConstructorImpl& operator=(
const VariantConstructorImpl& src) noexcept
278 if (this->GetIndex() == src.GetIndex())
280 src.CastAndCall(detail::VariantCopyFunctor{}, this->Storage);
285 src.CastAndCall(detail::VariantCopyConstructFunctor{}, this->Storage);
286 this->Index = src.Index;
299 template <
typename... Ts>
300 class Variant : detail::VariantConstructorImpl<Variant<Ts...>>
310 template <
typename T>
315 template <
typename T>
323 template <viskores::IdComponent Index>
331 template <
typename T>
336 template <
typename T>
360 return (this->Index >= 0) && (this->Index < NumberOfTypes);
365 template <
typename T>
368 return (this->GetIndex() == this->GetIndexOf<T>());
378 template <
typename T>
386 new (&this->Get<index>()) T(src);
389 template <
typename T>
392 if (this->IsType<T>())
394 this->Get<T>() = src;
398 this->Emplace<T>(src);
403 template <
typename T,
typename... Args>
408 return this->EmplaceImpl<T, I>(std::forward<Args>(args)...);
411 template <
typename T,
typename U,
typename... Args>
416 return this->EmplaceImpl<T, I>(il, std::forward<Args>(args)...);
423 "Variant::Emplace called with invalid index");
424 return this->EmplaceImpl<TypeAt<I>, I>(std::forward<Args>(args)...);
431 "Variant::Emplace called with invalid index");
432 return this->EmplaceImpl<TypeAt<I>, I>(il, std::forward<Args>(args)...);
441 return *(
new (&this->Get<I>()) T{ args... });
449 return *(
new (&this->Get<I>()) T(il, args...));
457 template <viskores::IdComponent I>
461 return detail::VariantUnionGet<I>(this->Storage);
464 template <viskores::IdComponent I>
468 return detail::VariantUnionGet<I>(this->Storage);
476 template <
typename T>
482 template <
typename T>
490 template <
typename T>
494 return detail::VariantUnionGet<IndexOf<T>::value>(this->Storage);
497 template <
typename T>
501 return detail::VariantUnionGet<IndexOf<T>::value>(this->Storage);
509 template <
typename T>
513 "Attempted to get a type from a variant that the variant does not contain.");
515 return *
reinterpret_cast<T*
>(0);
526 template <
typename Functor,
typename... Args>
528 noexcept(noexcept(f(std::declval<
const TypeAt<0>&>(), args...)))
531 return detail::VariantCastAndCallImpl<
sizeof...(Ts)>(
532 this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
535 template <
typename Functor,
typename... Args>
537 Args&&... args) noexcept(noexcept(f(std::declval<
TypeAt<0>&>(),
541 return detail::VariantCastAndCallImpl<
sizeof...(Ts)>(
542 this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
552 this->
CastAndCall(detail::VariantDestroyFunctor{});
560 template <
typename List>
565 #undef VISKORES_DEVICE
566 #undef VISKORES_NAMESPACE