From c9bcdd0195f9c7c3a16bb44e767a439220887f1f Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Wed, 17 Mar 2021 14:38:33 -0600 Subject: [PATCH 01/11] Use a union in Variant for safe type punning Create a `VaraintUnion` that is an actual C++ `union` to store the data in a `Variant`. You may be asking yourself, why not just use an `std::aligned_union` rather than a real union type? That was our first implementation, but the problem is that the `std::aligned_union` reference needs to be recast to the actual type. Typically you would do that with `reinterpret_cast`. However, doing that leads to undefined behavior. The C++ compiler assumes that 2 pointers of different types point to different memory (even if it is clear that they are set to the same address). That means optimizers can remove code because it "knows" that data in one type cannot affect data in another type. To safely change the type of an `std::aligned_union`, you really have to do an `std::memcpy`. This is problematic for types that cannot be trivially copied. Another problem is that we found that device compilers do not optimize the memcpy as well as most CPU compilers. Likely, memcpy is used much less frequently on GPU devices. --- .../exec/internal/testing/UnitTestVariant.cxx | 62 +- vtkm/internal/VariantImpl.h | 281 +- vtkm/internal/VariantImplDetail.h | 4051 ++++++++++------- vtkm/internal/VariantImplDetail.h.in | 335 +- 4 files changed, 2764 insertions(+), 1965 deletions(-) diff --git a/vtkm/exec/internal/testing/UnitTestVariant.cxx b/vtkm/exec/internal/testing/UnitTestVariant.cxx index 424665f1a..bc37bec6d 100644 --- a/vtkm/exec/internal/testing/UnitTestVariant.cxx +++ b/vtkm/exec/internal/testing/UnitTestVariant.cxx @@ -248,50 +248,51 @@ void TestTriviallyCopyable() VTKM_STATIC_ASSERT(!std::is_trivial::value); // A variant of trivially constructable things should be trivially constructable - VTKM_STATIC_ASSERT((vtkm::exec::internal::detail::AllTriviallyConstructible::value)); + VTKM_STATIC_ASSERT((vtkmstd::is_trivially_constructible< + vtkm::exec::internal::detail::VariantUnion>::value)); VTKM_STATIC_ASSERT( - (std::is_trivially_constructible>::value)); + (vtkmstd::is_trivially_constructible>::value)); // A variant of trivially copyable things should be trivially copyable - VTKM_STATIC_ASSERT( - (vtkm::exec::internal::detail::AllTriviallyCopyable::value)); - VTKM_STATIC_ASSERT( - (std::is_trivially_copyable>::value)); + VTKM_STATIC_ASSERT((vtkmstd::is_trivially_copyable< + vtkm::exec::internal::detail::VariantUnion>::value)); + VTKM_STATIC_ASSERT(( + vtkmstd::is_trivially_copyable>::value)); // A variant of any non-trivially constructable things is not trivially copyable - VTKM_STATIC_ASSERT( - (!vtkm::exec::internal::detail::AllTriviallyConstructible::value)); - VTKM_STATIC_ASSERT( - (!vtkm::exec::internal::detail::AllTriviallyConstructible::value)); - VTKM_STATIC_ASSERT( - (!vtkm::exec::internal::detail::AllTriviallyConstructible::value)); - VTKM_STATIC_ASSERT((!std::is_trivially_constructible< + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible< + vtkm::exec::internal::detail::VariantUnion>::value)); + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible< + vtkm::exec::internal::detail::VariantUnion>::value)); + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible< + vtkm::exec::internal::detail::VariantUnion>::value)); + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible< vtkm::exec::internal::Variant>::value)); - VTKM_STATIC_ASSERT((!std::is_trivially_constructible< + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible< vtkm::exec::internal::Variant>::value)); - VTKM_STATIC_ASSERT((!std::is_trivially_constructible< + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible< vtkm::exec::internal::Variant>::value)); // A variant of any non-trivially copyable things is not trivially copyable - VTKM_STATIC_ASSERT( - (!vtkm::exec::internal::detail::AllTriviallyCopyable::value)); - VTKM_STATIC_ASSERT( - (!vtkm::exec::internal::detail::AllTriviallyCopyable::value)); - VTKM_STATIC_ASSERT( - (!vtkm::exec::internal::detail::AllTriviallyCopyable::value)); - VTKM_STATIC_ASSERT( - (!std::is_trivially_copyable>::value)); - VTKM_STATIC_ASSERT( - (!std::is_trivially_copyable>::value)); - VTKM_STATIC_ASSERT( - (!std::is_trivially_copyable>::value)); + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable< + vtkm::exec::internal::detail::VariantUnion>::value)); + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable< + vtkm::exec::internal::detail::VariantUnion>::value)); + VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable< + vtkm::exec::internal::detail::VariantUnion>::value)); + VTKM_STATIC_ASSERT(( + !vtkmstd::is_trivially_copyable>::value)); + VTKM_STATIC_ASSERT(( + !vtkmstd::is_trivially_copyable>::value)); + VTKM_STATIC_ASSERT(( + !vtkmstd::is_trivially_copyable>::value)); // A variant of trivial things should be trivial - VTKM_STATIC_ASSERT((std::is_trivial>::value)); + VTKM_STATIC_ASSERT((vtkmstd::is_trivial>::value)); VTKM_STATIC_ASSERT( - (!std::is_trivial>::value)); + (!vtkmstd::is_trivial>::value)); VTKM_STATIC_ASSERT( - (!std::is_trivial>::value)); + (!vtkmstd::is_trivial>::value)); #endif // !VTKM_USING_GLIBCXX_4 } @@ -434,6 +435,7 @@ struct CountConstructDestruct ++(*this->Count); } ~CountConstructDestruct() { --(*this->Count); } + CountConstructDestruct& operator=(const CountConstructDestruct&) = delete; }; void TestCopyDestroy() diff --git a/vtkm/internal/VariantImpl.h b/vtkm/internal/VariantImpl.h index 64a7b387f..5e6784d14 100644 --- a/vtkm/internal/VariantImpl.h +++ b/vtkm/internal/VariantImpl.h @@ -20,8 +20,7 @@ #include #include -#include -#include +#include namespace vtkm { @@ -37,12 +36,33 @@ class Variant; namespace detail { +// -------------------------------------------------------------------------------- +// Helper classes for Variant + +template +struct VariantUnionToListImpl; +template +struct VariantUnionToListImpl> +{ + using type = vtkm::List; +}; +template +struct VariantUnionToListImpl> +{ + using type = vtkm::List; +}; + +template +using VariantUnionToList = + typename VariantUnionToListImpl::type>::type; + struct VariantCopyFunctor { - template - VTK_M_DEVICE void operator()(const T& src, void* destPointer) const noexcept + template + VTK_M_DEVICE void operator()(const T& src, UnionType& destUnion) const noexcept { - new (destPointer) T(src); + constexpr vtkm::IdComponent Index = vtkm::ListIndexOf, T>::value; + new (&VariantUnionGet(destUnion)) T(src); } }; @@ -68,115 +88,12 @@ struct VariantCheckType VTKM_STATIC_ASSERT_MSG(!std::is_pointer::value, "Pointers are not allowed in VTK-m Variant."); }; -template -struct AllTriviallyCopyable; - -template <> -struct AllTriviallyCopyable<> : std::true_type -{ -}; - -template -struct AllTriviallyCopyable - : std::integral_constant::value)> -{ -}; - -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value)> -{ -}; - -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value)> -{ -}; - -template -struct AllTriviallyCopyable - : std::integral_constant< - bool, - (vtkmstd::is_trivially_copyable::value && vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && vtkmstd::is_trivially_copyable::value)> -{ -}; - -template -struct AllTriviallyCopyable - : std::integral_constant< - bool, - (vtkmstd::is_trivially_copyable::value && vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && AllTriviallyCopyable::value)> -{ -}; - template struct VariantTriviallyCopyable; template struct VariantTriviallyCopyable> - : AllTriviallyCopyable -{ -}; - -template -struct AllTriviallyConstructible; - -template <> -struct AllTriviallyConstructible<> : std::true_type -{ -}; - -template -struct AllTriviallyConstructible - : std::integral_constant::value)> -{ -}; - -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value)> -{ -}; - -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value)> -{ -}; - -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value)> -{ -}; - -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - AllTriviallyConstructible::value)> + : vtkmstd::is_trivially_copyable> { }; @@ -185,26 +102,28 @@ struct VariantTriviallyConstructible; template struct VariantTriviallyConstructible> - : AllTriviallyConstructible + : vtkmstd::is_trivially_constructible> { }; +// -------------------------------------------------------------------------------- +// Variant superclass that defines its storage template struct VariantStorageImpl { - typename vtkmstd::aligned_union<0, Ts...>::type Storage; - + VariantUnion Storage; vtkm::IdComponent Index; + VariantStorageImpl() = default; + + VTK_M_DEVICE VariantStorageImpl(vtkm::internal::NullType dummy) + : Storage({ dummy }) + { + } + template using TypeAt = typename vtkm::ListAt, Index>; - VTK_M_DEVICE void* GetPointer() { return reinterpret_cast(&this->Storage); } - VTK_M_DEVICE const void* GetPointer() const - { - return reinterpret_cast(&this->Storage); - } - VTK_M_DEVICE vtkm::IdComponent GetIndex() const noexcept { return this->Index; } VTK_M_DEVICE bool IsValid() const noexcept { @@ -226,12 +145,11 @@ struct VariantStorageImpl -> decltype(f(std::declval&>(), args...)) { VTKM_ASSERT(this->IsValid()); - return detail::VariantCastAndCallImpl&>(), args...))>( - brigand::list{}, - this->GetIndex(), - std::forward(f), - this->GetPointer(), - std::forward(args)...); + return detail::VariantCastAndCallImpl(vtkm::ListSize>{}, + this->GetIndex(), + std::forward(f), + this->Storage, + std::forward(args)...); } template @@ -240,15 +158,17 @@ struct VariantStorageImpl -> decltype(f(std::declval&>(), args...)) { VTKM_ASSERT(this->IsValid()); - return detail::VariantCastAndCallImpl&>(), args...))>( - brigand::list{}, - this->GetIndex(), - std::forward(f), - this->GetPointer(), - std::forward(args)...); + return detail::VariantCastAndCallImpl(vtkm::ListSize>{}, + this->GetIndex(), + std::forward(f), + this->Storage, + std::forward(args)...); } }; +// -------------------------------------------------------------------------------- +// Variant superclass that helps preserve trivially copyable and trivially constructable +// properties where possible. template ::type, @@ -277,7 +197,11 @@ struct VariantConstructorImpl, std::false_type, std::true_type> : VariantStorageImpl { - VTK_M_DEVICE VariantConstructorImpl() { this->Index = -1; } + VTK_M_DEVICE VariantConstructorImpl() + : VariantStorageImpl(vtkm::internal::NullType{}) + { + this->Index = -1; + } // Any trivially copyable class is trivially destructable. ~VariantConstructorImpl() = default; @@ -294,19 +218,24 @@ struct VariantConstructorImpl, construct_type, std::false_type> : VariantStorageImpl { - VTK_M_DEVICE VariantConstructorImpl() { this->Index = -1; } + VTK_M_DEVICE VariantConstructorImpl() + : VariantStorageImpl(vtkm::internal::NullType{}) + { + this->Index = -1; + } VTK_M_DEVICE ~VariantConstructorImpl() { this->Reset(); } VTK_M_DEVICE VariantConstructorImpl(const VariantConstructorImpl& src) noexcept + : VariantStorageImpl(vtkm::internal::NullType{}) { - src.CastAndCall(VariantCopyFunctor{}, this->GetPointer()); + src.CastAndCall(VariantCopyFunctor{}, this->Storage); this->Index = src.Index; } VTK_M_DEVICE VariantConstructorImpl& operator=(const VariantConstructorImpl& src) noexcept { this->Reset(); - src.CastAndCall(detail::VariantCopyFunctor{}, this->GetPointer()); + src.CastAndCall(detail::VariantCopyFunctor{}, this->Storage); this->Index = src.Index; return *this; } @@ -323,20 +252,6 @@ class Variant : detail::VariantConstructorImpl> using CheckTypes = vtkm::List...>; public: - /// Returns the index of the type of object this variant is storing. If no object is currently - /// stored (i.e. the `Variant` is invalid), an invalid is returned. - /// - VTK_M_DEVICE vtkm::IdComponent GetIndex() const noexcept { return this->Superclass::GetIndex(); } - - /// Returns true if this `Variant` is storing an object from one of the types in the template - /// list, false otherwise. - /// - /// Note that if this `Variant` was not initialized with an object, the result of `IsValid` - /// is undefined. The `Variant` could report itself as validly containing an object that - /// is trivially constructed. - /// - VTK_M_DEVICE bool IsValid() const noexcept { return this->Superclass::IsValid(); } - /// Type that converts to a std::integral_constant containing the index of the given type (or /// -1 if that type is not in the list). template @@ -353,12 +268,29 @@ public: /// Type that converts to the type at the given index. /// template - using TypeAt = typename Superclass::template TypeAt; + using TypeAt = typename vtkm::ListAt, Index>; /// The number of types representable by this Variant. /// static constexpr vtkm::IdComponent NumberOfTypes = vtkm::IdComponent{ sizeof...(Ts) }; + /// Returns the index of the type of object this variant is storing. If no object is currently + /// stored (i.e. the `Variant` is invalid), an invalid is returned. + /// + VTK_M_DEVICE vtkm::IdComponent GetIndex() const noexcept { return this->Index; } + + /// Returns true if this `Variant` is storing an object from one of the types in the template + /// list, false otherwise. + /// + /// Note that if this `Variant` was not initialized with an object, the result of `IsValid` + /// is undefined. The `Variant` could report itself as validly containing an object that + /// is trivially constructed. + /// + VTK_M_DEVICE bool IsValid() const noexcept + { + return (this->Index >= 0) && (this->Index < NumberOfTypes); + } + Variant() = default; ~Variant() = default; Variant(const Variant&) = default; @@ -373,19 +305,15 @@ public: // Might be a way to use an enable_if to enforce a proper type. VTKM_STATIC_ASSERT_MSG(index >= 0, "Attempting to put invalid type into a Variant"); - new (this->GetPointer()) T(src); this->Index = index; + new (&this->Get()) T(src); } template - VTK_M_DEVICE Variant(const T&& src) noexcept + VTK_M_DEVICE Variant& operator=(const T& src) { - constexpr vtkm::IdComponent index = IndexOf::value; - // Might be a way to use an enable_if to enforce a proper type. - VTKM_STATIC_ASSERT_MSG(index >= 0, "Attempting to put invalid type into a Variant"); - - new (this->GetPointer()) T(std::move(src)); - this->Index = index; + this->Emplace(src); + return *this; } template @@ -425,18 +353,16 @@ private: VTK_M_DEVICE T& EmplaceImpl(Args&&... args) { this->Reset(); - T* value = new (this->GetPointer()) T{ args... }; this->Index = I; - return *value; + return *(new (&this->Get()) T{ args... }); } template VTK_M_DEVICE T& EmplaceImpl(std::initializer_list il, Args&&... args) { this->Reset(); - T* value = new (this->GetPointer()) T(il, args...); this->Index = I; - return *value; + return *(new (&this->Get()) T(il, args...)); } public: @@ -448,14 +374,14 @@ public: VTK_M_DEVICE TypeAt& Get() noexcept { VTKM_ASSERT(I == this->GetIndex()); - return *reinterpret_cast*>(this->GetPointer()); + return detail::VariantUnionGet(this->Storage); } template VTK_M_DEVICE const TypeAt& Get() const noexcept { VTKM_ASSERT(I == this->GetIndex()); - return *reinterpret_cast*>(this->GetPointer()); + return detail::VariantUnionGet(this->Storage); } //@} @@ -467,14 +393,14 @@ public: VTK_M_DEVICE T& Get() noexcept { VTKM_ASSERT(this->GetIndexOf() == this->GetIndex()); - return *reinterpret_cast(this->GetPointer()); + return detail::VariantUnionGet::value>(this->Storage); } template VTK_M_DEVICE const T& Get() const noexcept { VTKM_ASSERT(this->GetIndexOf() == this->GetIndex()); - return *reinterpret_cast(this->GetPointer()); + return detail::VariantUnionGet::value>(this->Storage); } //@} @@ -490,7 +416,13 @@ public: noexcept(noexcept(f(std::declval&>(), args...))) -> decltype(f(std::declval&>(), args...)) { - return this->Superclass::CastAndCall(std::forward(f), std::forward(args)...); + VTKM_ASSERT(this->IsValid()); + return detail::VariantCastAndCallImpl( + std::integral_constant{}, + this->GetIndex(), + std::forward(f), + this->Storage, + std::forward(args)...); } template @@ -498,13 +430,26 @@ public: noexcept(f(std::declval&>(), args...))) -> decltype(f(std::declval&>(), args...)) { - return this->Superclass::CastAndCall(std::forward(f), std::forward(args)...); + VTKM_ASSERT(this->IsValid()); + return detail::VariantCastAndCallImpl( + std::integral_constant{}, + this->GetIndex(), + std::forward(f), + this->Storage, + std::forward(args)...); } /// Destroys any object the Variant is holding and sets the Variant to an invalid state. This /// method is not thread safe. /// - VTK_M_DEVICE void Reset() noexcept { this->Superclass::Reset(); } + VTK_M_DEVICE void Reset() noexcept + { + if (this->IsValid()) + { + this->CastAndCall(detail::VariantDestroyFunctor{}); + this->Index = -1; + } + } }; /// \brief Convert a ListTag to a Variant. diff --git a/vtkm/internal/VariantImplDetail.h b/vtkm/internal/VariantImplDetail.h index 4211ff916..a2efcde54 100644 --- a/vtkm/internal/VariantImplDetail.h +++ b/vtkm/internal/VariantImplDetail.h @@ -19,7 +19,9 @@ #include -#include +#include + +#include #include @@ -45,2136 +47,2845 @@ struct VariantDummyReturn VTK_M_DEVICE static inline void F() noexcept {} }; -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl(brigand::list<>, - vtkm::IdComponent, - Functor&&, - const void*, - Args&&...) noexcept -{ - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); -} - // clang-format off -template +struct AllTriviallyCopyable; + +template +struct AllTriviallyCopyable + : std::integral_constant::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + true)> { }; +template +struct AllTriviallyCopyable + : std::integral_constant::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + vtkmstd::is_trivially_copyable::value && + AllTriviallyCopyable::value)> { }; + +template +struct AllTriviallyConstructible; + +template +struct AllTriviallyConstructible + : std::integral_constant::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + true)> { }; +template +struct AllTriviallyConstructible + : std::integral_constant::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + vtkmstd::is_trivially_constructible::value && + AllTriviallyConstructible::value)> { }; + +template +struct AllTriviallyDestructible; + +template +struct AllTriviallyDestructible + : std::integral_constant::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + true)> { }; +template +struct AllTriviallyDestructible + : std::integral_constant::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + vtkmstd::is_trivially_destructible::value && + AllTriviallyDestructible::value)> { }; + +// -------------------------------------------------------------------------------- +// Union type used inside of Variant +// +// You may be asking yourself, why not just use an std::aligned_union rather than a real union +// type? That was our first implementation, but the problem is that the std::aligned_union +// reference needs to be recast to the actual type. Typically you would do that with +// reinterpret_cast. However, doing that leads to undefined behavior. The C++ compiler assumes that +// 2 pointers of different types point to different memory (even if it is clear that they are set +// to the same address). That means optimizers can remove code because it "knows" that data in one +// type cannot affect data in another type. To safely change the type of an std::aligned_union, +// you really have to do an std::memcpy. This is problematic for types that cannot be trivially +// copied. Another problem is that we found that device compilers do not optimize the memcpy +// as well as most CPU compilers. Likely, memcpy is used much less frequently on GPU devices. +// +// Part of the trickiness of the union implementation is trying to preserve when the type is +// trivially constructible and copyable. The trick is that if members of the union are not trivial, +// then the default constructors are deleted. To get around that, a non-default constructor is +// added, which we can use to construct the union for non-trivial types. Working with types with +// non-trivial destructors are particularly trick. Again, if any member of the union has a +// non-trivial destructor, the destructor is deleted. Unlike a constructor, you cannot just say to +// use a different destructor. Thus, we have to define our own destructor for the union. +// Technically, the destructor here does not do anything, but the actual destruction should be +// handled by the Variant class that contains this VariantUnion. We actually need two separate +// implementations of our union, one that defines a destructor and one that use the default +// destructor. If you define your own destructor, you can lose the trivial constructor and trivial +// copy properties. +// + +// TD = trivially deconstructible +template +union VariantUnionTD; + +// NTD = non-trivially deconstructible +template +union VariantUnionNTD; + +template +union VariantUnionTD +{ + T0 V0; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + T18 V18; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + T18 V18; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +union VariantUnionTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + T18 V18; + T19 V19; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + T18 V18; + T19 V19; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + + +template +union VariantUnionTD +{ + vtkm::internal::NullType Dummy; + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + T18 V18; + T19 V19; + VariantUnionTD Remaining; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template +union VariantUnionNTD +{ + vtkm::internal::NullType Dummy; + T0 V0; + T1 V1; + T2 V2; + T3 V3; + T4 V4; + T5 V5; + T6 V6; + T7 V7; + T8 V8; + T9 V9; + T10 V10; + T11 V11; + T12 V12; + T13 V13; + T14 V14; + T15 V15; + T16 V16; + T17 V17; + T18 V18; + T19 V19; + VariantUnionNTD Remaining; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +struct VariantUnionFinder; + +template +struct VariantUnionFinder +{ + using type = VariantUnionTD; +}; +template +struct VariantUnionFinder +{ + using type = VariantUnionNTD; +}; + +template +using VariantUnion = + typename VariantUnionFinder::value, Ts...>::type; + +// -------------------------------------------------------------------------------- +// Methods to get values out of the variant union +template +struct VariantUnionGetImpl; + +template +struct VariantUnionGetImpl<0, UnionType> +{ + using ReturnType = decltype(std::declval().V0)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V0; + } +}; + +template +struct VariantUnionGetImpl<1, UnionType> +{ + using ReturnType = decltype(std::declval().V1)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V1; + } +}; + +template +struct VariantUnionGetImpl<2, UnionType> +{ + using ReturnType = decltype(std::declval().V2)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V2; + } +}; + +template +struct VariantUnionGetImpl<3, UnionType> +{ + using ReturnType = decltype(std::declval().V3)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V3; + } +}; + +template +struct VariantUnionGetImpl<4, UnionType> +{ + using ReturnType = decltype(std::declval().V4)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V4; + } +}; + +template +struct VariantUnionGetImpl<5, UnionType> +{ + using ReturnType = decltype(std::declval().V5)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V5; + } +}; + +template +struct VariantUnionGetImpl<6, UnionType> +{ + using ReturnType = decltype(std::declval().V6)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V6; + } +}; + +template +struct VariantUnionGetImpl<7, UnionType> +{ + using ReturnType = decltype(std::declval().V7)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V7; + } +}; + +template +struct VariantUnionGetImpl<8, UnionType> +{ + using ReturnType = decltype(std::declval().V8)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V8; + } +}; + +template +struct VariantUnionGetImpl<9, UnionType> +{ + using ReturnType = decltype(std::declval().V9)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V9; + } +}; + +template +struct VariantUnionGetImpl<10, UnionType> +{ + using ReturnType = decltype(std::declval().V10)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V10; + } +}; + +template +struct VariantUnionGetImpl<11, UnionType> +{ + using ReturnType = decltype(std::declval().V11)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V11; + } +}; + +template +struct VariantUnionGetImpl<12, UnionType> +{ + using ReturnType = decltype(std::declval().V12)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V12; + } +}; + +template +struct VariantUnionGetImpl<13, UnionType> +{ + using ReturnType = decltype(std::declval().V13)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V13; + } +}; + +template +struct VariantUnionGetImpl<14, UnionType> +{ + using ReturnType = decltype(std::declval().V14)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V14; + } +}; + +template +struct VariantUnionGetImpl<15, UnionType> +{ + using ReturnType = decltype(std::declval().V15)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V15; + } +}; + +template +struct VariantUnionGetImpl<16, UnionType> +{ + using ReturnType = decltype(std::declval().V16)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V16; + } +}; + +template +struct VariantUnionGetImpl<17, UnionType> +{ + using ReturnType = decltype(std::declval().V17)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V17; + } +}; + +template +struct VariantUnionGetImpl<18, UnionType> +{ + using ReturnType = decltype(std::declval().V18)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V18; + } +}; + +template +struct VariantUnionGetImpl<19, UnionType> +{ + using ReturnType = decltype(std::declval().V19)&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V19; + } +}; + + +template +struct VariantUnionGetImpl +{ + VTKM_STATIC_ASSERT(I >= 20); + using RecursiveGet = VariantUnionGetImpl().Remaining)>; + using ReturnType = typename RecursiveGet::ReturnType; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return RecursiveGet::Get(storage.Remaining); + } +}; + +template +VTK_M_DEVICE typename VariantUnionGetImpl::ReturnType +VariantUnionGet(UnionType& storage) noexcept +{ + return VariantUnionGetImpl::Get(storage); +} + +// -------------------------------------------------------------------------------- +// Internal implementation of CastAndCall for Variant +template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V13, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V13, std::forward(args)...); case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V14, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V13, std::forward(args)...); case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V14, std::forward(args)...); case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V15, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V13, std::forward(args)...); case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V14, std::forward(args)...); case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V15, std::forward(args)...); case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V16, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V13, std::forward(args)...); case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V14, std::forward(args)...); case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V15, std::forward(args)...); case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V16, std::forward(args)...); case 17: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V17, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V13, std::forward(args)...); case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V14, std::forward(args)...); case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V15, std::forward(args)...); case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V16, std::forward(args)...); case 17: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 17: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V17, std::forward(args)...); case 18: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V18, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V0, std::forward(args)...); case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V1, std::forward(args)...); case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V2, std::forward(args)...); case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V3, std::forward(args)...); case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V4, std::forward(args)...); case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V5, std::forward(args)...); case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V6, std::forward(args)...); case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V7, std::forward(args)...); case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V8, std::forward(args)...); case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V9, std::forward(args)...); case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V10, std::forward(args)...); case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V11, std::forward(args)...); case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V12, std::forward(args)...); case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V13, std::forward(args)...); case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V14, std::forward(args)...); case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V15, std::forward(args)...); case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V16, std::forward(args)...); case 17: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V17, std::forward(args)...); case 18: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 17: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 18: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V18, std::forward(args)...); case 19: - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V19, std::forward(args)...); default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - switch (index) - { - case 0: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 1: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 2: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 3: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 4: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 5: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 6: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 7: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 8: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 9: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 10: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 11: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 12: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 13: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 14: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 15: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 16: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 17: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 18: - return f(*reinterpret_cast(storage), std::forward(args)...); - case 19: - return f(*reinterpret_cast(storage), std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } //clang-format on // Recurse for cases where Variant has more than 20 types -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { - if (index < 20) + switch (index) { - return VariantCastAndCallImpl( - brigand::list{}, - index, - f, - storage, - args...); - } - else - { - return VariantCastAndCallImpl( - brigand::list{}, index - 20, f, storage, args...); - } -} - -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list, - vtkm::IdComponent index, - Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - if (index < 20) - { - return VariantCastAndCallImpl( - brigand::list{}, - index, - f, - storage, - args...); - } - else - { - return VariantCastAndCallImpl( - brigand::list{}, index - 20, f, storage, args...); + case 0: + return f(storage.V0, std::forward(args)...); + case 1: + return f(storage.V1, std::forward(args)...); + case 2: + return f(storage.V2, std::forward(args)...); + case 3: + return f(storage.V3, std::forward(args)...); + case 4: + return f(storage.V4, std::forward(args)...); + case 5: + return f(storage.V5, std::forward(args)...); + case 6: + return f(storage.V6, std::forward(args)...); + case 7: + return f(storage.V7, std::forward(args)...); + case 8: + return f(storage.V8, std::forward(args)...); + case 9: + return f(storage.V9, std::forward(args)...); + case 10: + return f(storage.V10, std::forward(args)...); + case 11: + return f(storage.V11, std::forward(args)...); + case 12: + return f(storage.V12, std::forward(args)...); + case 13: + return f(storage.V13, std::forward(args)...); + case 14: + return f(storage.V14, std::forward(args)...); + case 15: + return f(storage.V15, std::forward(args)...); + case 16: + return f(storage.V16, std::forward(args)...); + case 17: + return f(storage.V17, std::forward(args)...); + case 18: + return f(storage.V18, std::forward(args)...); + case 19: + return f(storage.V19, std::forward(args)...); + default: + return VariantCastAndCallImpl(std::integral_constant{}, + index - 20, + std::forward(f), + storage.Remaining, + std::forward(args)...); } } diff --git a/vtkm/internal/VariantImplDetail.h.in b/vtkm/internal/VariantImplDetail.h.in index 0801dc812..d116558ce 100644 --- a/vtkm/internal/VariantImplDetail.h.in +++ b/vtkm/internal/VariantImplDetail.h.in @@ -31,7 +31,9 @@ $# Ignore the following comment. It is meant for the generated file. #include -#include +#include + +#include #include @@ -46,9 +48,17 @@ def type_list(num_params): for param in range(1, num_params + 1): result += ', T%d' % param return result + +def typename_list(num_params): + if num_params < 0: + return '' + result = 'typename T0' + for param in range(1, num_params + 1): + result += ', typename T%d' % param + return result )\ $# -$extend(type_list)\ +$extend(type_list, typename_list)\ namespace vtkm { @@ -70,70 +80,234 @@ struct VariantDummyReturn VTK_M_DEVICE static inline void F() noexcept {} }; -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl(brigand::list<>, - vtkm::IdComponent, - Functor&&, - const void*, - Args&&...) noexcept -{ - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); -} - // clang-format off -$for(num_params in range(0, max_expanded))\ -template +struct AllTriviallyCopyable; + +$for(num_params in range(max_expanded))\ +template <$typename_list(num_params)> +struct AllTriviallyCopyable<$type_list(num_params)> + : std::integral_constant::value && +$for(param_index in range(1, num_params + 1))\ + vtkmstd::is_trivially_copyable::value && $endfor\ - typename Functor, - typename... Args> -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list<$type_list(num_params)>, - vtkm::IdComponent index, - Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + true)> { }; +$endfor\ +template <$typename_list(max_expanded), typename... Ts> +struct AllTriviallyCopyable<$type_list(max_expanded), Ts...> + : std::integral_constant::value && +$for(param_index in range(1, max_expanded))\ + vtkmstd::is_trivially_copyable::value && +$endfor\ + AllTriviallyCopyable::value)> { }; + +template +struct AllTriviallyConstructible; + +$for(num_params in range(max_expanded))\ +template <$typename_list(num_params)> +struct AllTriviallyConstructible<$type_list(num_params)> + : std::integral_constant::value && +$for(param_index in range(1, num_params + 1))\ + vtkmstd::is_trivially_constructible::value && +$endfor\ + true)> { }; +$endfor\ +template <$typename_list(max_expanded), typename... Ts> +struct AllTriviallyConstructible<$type_list(max_expanded), Ts...> + : std::integral_constant::value && +$for(param_index in range(1, max_expanded))\ + vtkmstd::is_trivially_constructible::value && +$endfor\ + AllTriviallyConstructible::value)> { }; + +template +struct AllTriviallyDestructible; + +$for(num_params in range(max_expanded))\ +template <$typename_list(num_params)> +struct AllTriviallyDestructible<$type_list(num_params)> + : std::integral_constant::value && +$for(param_index in range(1, num_params + 1))\ + vtkmstd::is_trivially_destructible::value && +$endfor\ + true)> { }; +$endfor\ +template <$typename_list(max_expanded), typename... Ts> +struct AllTriviallyDestructible<$type_list(max_expanded), Ts...> + : std::integral_constant::value && +$for(param_index in range(1, max_expanded))\ + vtkmstd::is_trivially_destructible::value && +$endfor\ + AllTriviallyDestructible::value)> { }; + +// -------------------------------------------------------------------------------- +// Union type used inside of Variant +// +// You may be asking yourself, why not just use an std::aligned_union rather than a real union +// type? That was our first implementation, but the problem is that the std::aligned_union +// reference needs to be recast to the actual type. Typically you would do that with +// reinterpret_cast. However, doing that leads to undefined behavior. The C++ compiler assumes that +// 2 pointers of different types point to different memory (even if it is clear that they are set +// to the same address). That means optimizers can remove code because it "knows" that data in one +// type cannot affect data in another type. To safely change the type of an std::aligned_union, +// you really have to do an std::memcpy. This is problematic for types that cannot be trivially +// copied. Another problem is that we found that device compilers do not optimize the memcpy +// as well as most CPU compilers. Likely, memcpy is used much less frequently on GPU devices. +// +// Part of the trickiness of the union implementation is trying to preserve when the type is +// trivially constructible and copyable. The trick is that if members of the union are not trivial, +// then the default constructors are deleted. To get around that, a non-default constructor is +// added, which we can use to construct the union for non-trivial types. Working with types with +// non-trivial destructors are particularly trick. Again, if any member of the union has a +// non-trivial destructor, the destructor is deleted. Unlike a constructor, you cannot just say to +// use a different destructor. Thus, we have to define our own destructor for the union. +// Technically, the destructor here does not do anything, but the actual destruction should be +// handled by the Variant class that contains this VariantUnion. We actually need two separate +// implementations of our union, one that defines a destructor and one that use the default +// destructor. If you define your own destructor, you can lose the trivial constructor and trivial +// copy properties. +// + +// TD = trivially deconstructible +template +union VariantUnionTD; + +// NTD = non-trivially deconstructible +template +union VariantUnionNTD; + +$for(num_params in range(max_expanded))\ +template <$typename_list(num_params)> +union VariantUnionTD<$type_list(num_params)> { - switch (index) - { -$for(param_index in range(0, num_params + 1))\ - case $(param_index): - return f(*reinterpret_cast(storage), std::forward(args)...); +$for(param_index in range(num_params + 1))\ + T$(param_index) V$(param_index); $endfor\ - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template <$typename_list(num_params)> +union VariantUnionNTD<$type_list(num_params)> +{ +$for(param_index in range(num_params + 1))\ + T$(param_index) V$(param_index); +$endfor\ + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +$endfor\ + +template <$typename_list(max_expanded), typename... Ts> +union VariantUnionTD<$type_list(max_expanded), Ts...> +{ + vtkm::internal::NullType Dummy; +$for(param_index in range(max_expanded))\ + T$(param_index) V$(param_index); +$endfor\ + VariantUnionTD Remaining; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } + VariantUnionTD() = default; +}; + +template <$typename_list(max_expanded), typename... Ts> +union VariantUnionNTD<$type_list(max_expanded), Ts...> +{ + vtkm::internal::NullType Dummy; +$for(param_index in range(max_expanded))\ + T$(param_index) V$(param_index); +$endfor\ + VariantUnionNTD Remaining; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } + VariantUnionNTD() = default; + VTK_M_DEVICE ~VariantUnionNTD() { } +}; + +template +struct VariantUnionFinder; + +template +struct VariantUnionFinder +{ + using type = VariantUnionTD; +}; +template +struct VariantUnionFinder +{ + using type = VariantUnionNTD; +}; + +template +using VariantUnion = + typename VariantUnionFinder::value, Ts...>::type; + +// -------------------------------------------------------------------------------- +// Methods to get values out of the variant union +template +struct VariantUnionGetImpl; + +$for(param_index in range(max_expanded))\ +template +struct VariantUnionGetImpl<$(param_index), UnionType> +{ + using ReturnType = decltype(std::declval().V$(param_index))&; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return storage.V$(param_index); } +}; + +$endfor\ + +template +struct VariantUnionGetImpl +{ + VTKM_STATIC_ASSERT(I >= $(max_expanded)); + using RecursiveGet = VariantUnionGetImpl().Remaining)>; + using ReturnType = typename RecursiveGet::ReturnType; + VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + { + return RecursiveGet::Get(storage.Remaining); + } +}; + +template +VTK_M_DEVICE typename VariantUnionGetImpl::ReturnType +VariantUnionGet(UnionType& storage) noexcept +{ + return VariantUnionGetImpl::Get(storage); } -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list<$type_list(num_params)>, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { switch (index) { -$for(param_index in range(0, num_params + 1))\ +$for(param_index in range(num_params + 1))\ case $(param_index): - return f(*reinterpret_cast(storage), std::forward(args)...); + return f(storage.V$(param_index), std::forward(args)...); $endfor\ default: // If we are here, it means we failed to find the appropriate type in a variant VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); + return VariantDummyReturn::F(); } } @@ -141,63 +315,30 @@ $endfor\ //clang-format on // Recurse for cases where Variant has more than $(max_expanded) types -template -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list<$type_list(max_expanded), RemainingT...>, +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + std::integral_constant, vtkm::IdComponent index, Functor&& f, - const void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) { - if (index < $(max_expanded)) + switch (index) { - return VariantCastAndCallImpl( - brigand::list<$type_list(max_expanded - 1)>{}, - index, - f, - storage, - args...); - } - else - { - return VariantCastAndCallImpl( - brigand::list{}, index - $(max_expanded), f, storage, args...); - } -} - -template (args)...); $endfor\ - typename... RemainingT, - typename Functor, - typename... Args> -VTK_M_DEVICE inline ReturnType VariantCastAndCallImpl( - brigand::list<$type_list(max_expanded), RemainingT...>, - vtkm::IdComponent index, - Functor&& f, - void* storage, - Args&&... args) noexcept(noexcept(f(std::declval(), args...))) -{ - if (index < $(max_expanded)) - { - return VariantCastAndCallImpl( - brigand::list<$type_list(max_expanded - 1)>{}, - index, - f, - storage, - args...); - } - else - { - return VariantCastAndCallImpl( - brigand::list{}, index - $(max_expanded), f, storage, args...); + default: + return VariantCastAndCallImpl(std::integral_constant{}, + index - $(max_expanded), + std::forward(f), + storage.Remaining, + std::forward(args)...); } } From cb60401a63a7be8394aa8f995ce0414eaeaf2d6f Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 23 Mar 2021 13:30:55 -0600 Subject: [PATCH 02/11] Use specialized class instead of function overload for Variant::Get Nvcc was having troubles resolving the return type of the overloaded function to get a value out of a `VariantUnion`. Replace the implementation with a class with specializations. This is more verbose, but easier on the compiler. --- vtkm/internal/VariantImplDetail.h | 174 ++++++++++++++++++++------- vtkm/internal/VariantImplDetail.h.in | 22 ++-- 2 files changed, 144 insertions(+), 52 deletions(-) diff --git a/vtkm/internal/VariantImplDetail.h b/vtkm/internal/VariantImplDetail.h index a2efcde54..993d8469c 100644 --- a/vtkm/internal/VariantImplDetail.h +++ b/vtkm/internal/VariantImplDetail.h @@ -1784,8 +1784,12 @@ struct VariantUnionGetImpl; template struct VariantUnionGetImpl<0, UnionType> { - using ReturnType = decltype(std::declval().V0)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V0); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V0; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V0; } @@ -1794,8 +1798,12 @@ struct VariantUnionGetImpl<0, UnionType> template struct VariantUnionGetImpl<1, UnionType> { - using ReturnType = decltype(std::declval().V1)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V1); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V1; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V1; } @@ -1804,8 +1812,12 @@ struct VariantUnionGetImpl<1, UnionType> template struct VariantUnionGetImpl<2, UnionType> { - using ReturnType = decltype(std::declval().V2)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V2); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V2; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V2; } @@ -1814,8 +1826,12 @@ struct VariantUnionGetImpl<2, UnionType> template struct VariantUnionGetImpl<3, UnionType> { - using ReturnType = decltype(std::declval().V3)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V3); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V3; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V3; } @@ -1824,8 +1840,12 @@ struct VariantUnionGetImpl<3, UnionType> template struct VariantUnionGetImpl<4, UnionType> { - using ReturnType = decltype(std::declval().V4)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V4); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V4; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V4; } @@ -1834,8 +1854,12 @@ struct VariantUnionGetImpl<4, UnionType> template struct VariantUnionGetImpl<5, UnionType> { - using ReturnType = decltype(std::declval().V5)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V5); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V5; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V5; } @@ -1844,8 +1868,12 @@ struct VariantUnionGetImpl<5, UnionType> template struct VariantUnionGetImpl<6, UnionType> { - using ReturnType = decltype(std::declval().V6)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V6); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V6; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V6; } @@ -1854,8 +1882,12 @@ struct VariantUnionGetImpl<6, UnionType> template struct VariantUnionGetImpl<7, UnionType> { - using ReturnType = decltype(std::declval().V7)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V7); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V7; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V7; } @@ -1864,8 +1896,12 @@ struct VariantUnionGetImpl<7, UnionType> template struct VariantUnionGetImpl<8, UnionType> { - using ReturnType = decltype(std::declval().V8)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V8); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V8; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V8; } @@ -1874,8 +1910,12 @@ struct VariantUnionGetImpl<8, UnionType> template struct VariantUnionGetImpl<9, UnionType> { - using ReturnType = decltype(std::declval().V9)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V9); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V9; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V9; } @@ -1884,8 +1924,12 @@ struct VariantUnionGetImpl<9, UnionType> template struct VariantUnionGetImpl<10, UnionType> { - using ReturnType = decltype(std::declval().V10)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V10); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V10; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V10; } @@ -1894,8 +1938,12 @@ struct VariantUnionGetImpl<10, UnionType> template struct VariantUnionGetImpl<11, UnionType> { - using ReturnType = decltype(std::declval().V11)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V11); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V11; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V11; } @@ -1904,8 +1952,12 @@ struct VariantUnionGetImpl<11, UnionType> template struct VariantUnionGetImpl<12, UnionType> { - using ReturnType = decltype(std::declval().V12)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V12); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V12; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V12; } @@ -1914,8 +1966,12 @@ struct VariantUnionGetImpl<12, UnionType> template struct VariantUnionGetImpl<13, UnionType> { - using ReturnType = decltype(std::declval().V13)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V13); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V13; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V13; } @@ -1924,8 +1980,12 @@ struct VariantUnionGetImpl<13, UnionType> template struct VariantUnionGetImpl<14, UnionType> { - using ReturnType = decltype(std::declval().V14)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V14); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V14; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V14; } @@ -1934,8 +1994,12 @@ struct VariantUnionGetImpl<14, UnionType> template struct VariantUnionGetImpl<15, UnionType> { - using ReturnType = decltype(std::declval().V15)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V15); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V15; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V15; } @@ -1944,8 +2008,12 @@ struct VariantUnionGetImpl<15, UnionType> template struct VariantUnionGetImpl<16, UnionType> { - using ReturnType = decltype(std::declval().V16)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V16); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V16; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V16; } @@ -1954,8 +2022,12 @@ struct VariantUnionGetImpl<16, UnionType> template struct VariantUnionGetImpl<17, UnionType> { - using ReturnType = decltype(std::declval().V17)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V17); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V17; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V17; } @@ -1964,8 +2036,12 @@ struct VariantUnionGetImpl<17, UnionType> template struct VariantUnionGetImpl<18, UnionType> { - using ReturnType = decltype(std::declval().V18)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V18); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V18; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V18; } @@ -1974,8 +2050,12 @@ struct VariantUnionGetImpl<18, UnionType> template struct VariantUnionGetImpl<19, UnionType> { - using ReturnType = decltype(std::declval().V19)&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V19); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V19; + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V19; } @@ -1986,19 +2066,23 @@ template struct VariantUnionGetImpl { VTKM_STATIC_ASSERT(I >= 20); - using RecursiveGet = VariantUnionGetImpl().Remaining)>; + using RecursiveGet = VariantUnionGetImpl().Remaining)>; using ReturnType = typename RecursiveGet::ReturnType; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return RecursiveGet::Get(storage.Remaining); + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return RecursiveGet::Get(storage.Remaining); } }; template -VTK_M_DEVICE typename VariantUnionGetImpl::ReturnType -VariantUnionGet(UnionType& storage) noexcept +VTK_M_DEVICE auto VariantUnionGet(UnionType& storage) noexcept + -> decltype(VariantUnionGetImpl::type>::Get(storage))& { - return VariantUnionGetImpl::Get(storage); + return VariantUnionGetImpl::type>::Get(storage); } // -------------------------------------------------------------------------------- diff --git a/vtkm/internal/VariantImplDetail.h.in b/vtkm/internal/VariantImplDetail.h.in index d116558ce..34e43465c 100644 --- a/vtkm/internal/VariantImplDetail.h.in +++ b/vtkm/internal/VariantImplDetail.h.in @@ -256,8 +256,12 @@ $for(param_index in range(max_expanded))\ template struct VariantUnionGetImpl<$(param_index), UnionType> { - using ReturnType = decltype(std::declval().V$(param_index))&; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + using ReturnType = decltype(std::declval().V$(param_index)); + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return storage.V$(param_index); + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return storage.V$(param_index); } @@ -269,19 +273,23 @@ template struct VariantUnionGetImpl { VTKM_STATIC_ASSERT(I >= $(max_expanded)); - using RecursiveGet = VariantUnionGetImpl().Remaining)>; + using RecursiveGet = VariantUnionGetImpl().Remaining)>; using ReturnType = typename RecursiveGet::ReturnType; - VTK_M_DEVICE static ReturnType Get(UnionType& storage) noexcept + VTK_M_DEVICE static ReturnType& Get(UnionType& storage) noexcept + { + return RecursiveGet::Get(storage.Remaining); + } + VTK_M_DEVICE static const ReturnType& Get(const UnionType& storage) noexcept { return RecursiveGet::Get(storage.Remaining); } }; template -VTK_M_DEVICE typename VariantUnionGetImpl::ReturnType -VariantUnionGet(UnionType& storage) noexcept +VTK_M_DEVICE auto VariantUnionGet(UnionType& storage) noexcept + -> decltype(VariantUnionGetImpl::type>::Get(storage))& { - return VariantUnionGetImpl::Get(storage); + return VariantUnionGetImpl::type>::Get(storage); } // -------------------------------------------------------------------------------- From cad5dc7b711e30bc41fb98b906dccf8bfa75d5fc Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 23 Mar 2021 13:34:39 -0600 Subject: [PATCH 03/11] Avoid is_trivially_copyable on VariantUnion For some reason some versions of the CUDA compiler would return true for `is_trivially_copyable` on a `VariantUnion` even when the types of the union caused the copy constructor to get deleted. Solve the problem by using `AllTriviallyCopyable` instead of directly caling `is_trivially_copyable` on the union. --- vtkm/internal/VariantImpl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vtkm/internal/VariantImpl.h b/vtkm/internal/VariantImpl.h index 5e6784d14..11acef38e 100644 --- a/vtkm/internal/VariantImpl.h +++ b/vtkm/internal/VariantImpl.h @@ -93,7 +93,7 @@ struct VariantTriviallyCopyable; template struct VariantTriviallyCopyable> - : vtkmstd::is_trivially_copyable> + : AllTriviallyCopyable { }; @@ -102,7 +102,7 @@ struct VariantTriviallyConstructible; template struct VariantTriviallyConstructible> - : vtkmstd::is_trivially_constructible> + : AllTriviallyConstructible { }; From d2d9ba3321d59b8b2d97e0b77836b4f20e1779d5 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 22 Feb 2021 08:44:23 -0700 Subject: [PATCH 04/11] Make connectivity structures trivially copyable It always worked to trivially copy these classes, but the compiler did not think so because copy constructors were defined. Change these constructors to be default so that the compler can properly check triviality. --- vtkm/exec/ConnectivityPermuted.h | 16 +++------------- vtkm/exec/ConnectivityStructured.h | 12 ++---------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/vtkm/exec/ConnectivityPermuted.h b/vtkm/exec/ConnectivityPermuted.h index da47f187b..5db3c29bc 100644 --- a/vtkm/exec/ConnectivityPermuted.h +++ b/vtkm/exec/ConnectivityPermuted.h @@ -27,13 +27,7 @@ class ConnectivityPermutedVisitCellsWithPoints public: using SchedulingRangeType = typename OriginalConnectivity::SchedulingRangeType; - VTKM_SUPPRESS_EXEC_WARNINGS - VTKM_EXEC_CONT - ConnectivityPermutedVisitCellsWithPoints() - : Portal() - , Connectivity() - { - } + ConnectivityPermutedVisitCellsWithPoints() = default; VTKM_EXEC_CONT ConnectivityPermutedVisitCellsWithPoints(const PermutationPortal& portal, @@ -43,12 +37,8 @@ public: { } - VTKM_EXEC_CONT - ConnectivityPermutedVisitCellsWithPoints(const ConnectivityPermutedVisitCellsWithPoints& src) - : Portal(src.Portal) - , Connectivity(src.Connectivity) - { - } + ConnectivityPermutedVisitCellsWithPoints(const ConnectivityPermutedVisitCellsWithPoints& src) = + default; ConnectivityPermutedVisitCellsWithPoints& operator=( const ConnectivityPermutedVisitCellsWithPoints& src) = default; diff --git a/vtkm/exec/ConnectivityStructured.h b/vtkm/exec/ConnectivityStructured.h index 65a30d925..0f14923c3 100644 --- a/vtkm/exec/ConnectivityStructured.h +++ b/vtkm/exec/ConnectivityStructured.h @@ -34,11 +34,7 @@ class ConnectivityStructured public: using SchedulingRangeType = typename InternalsType::SchedulingRangeType; - VTKM_EXEC_CONT - ConnectivityStructured() - : Internals() - { - } + ConnectivityStructured() = default; VTKM_EXEC_CONT ConnectivityStructured(const InternalsType& src) @@ -46,11 +42,7 @@ public: { } - VTKM_EXEC_CONT - ConnectivityStructured(const ConnectivityStructured& src) - : Internals(src.Internals) - { - } + ConnectivityStructured(const ConnectivityStructured& src) = default; VTKM_EXEC_CONT ConnectivityStructured( From e480fd7a24f2e39bf073bd37f1ad518be3f9e297 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Wed, 24 Mar 2021 14:41:31 -0600 Subject: [PATCH 05/11] Support copying a Variant to itself --- .../exec/internal/testing/UnitTestVariant.cxx | 30 +++++++--- vtkm/internal/VariantImpl.h | 60 +++++++++++++++++-- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/vtkm/exec/internal/testing/UnitTestVariant.cxx b/vtkm/exec/internal/testing/UnitTestVariant.cxx index bc37bec6d..fd3040968 100644 --- a/vtkm/exec/internal/testing/UnitTestVariant.cxx +++ b/vtkm/exec/internal/testing/UnitTestVariant.cxx @@ -34,7 +34,7 @@ static vtkm::Id g_NonTrivialCount; // A class that must is not trivial to copy nor construct. struct NonTrivial { - vtkm::Id Value = 12345; + vtkm::Id Value; NonTrivial* Self; void CheckState() const @@ -44,17 +44,19 @@ struct NonTrivial } NonTrivial() - : Self(this) + : Value(12345) + , Self(this) { this->CheckState(); ++g_NonTrivialCount; } NonTrivial(const NonTrivial& src) - : Self(this) + : Value(src.Value) { - this->CheckState(); src.CheckState(); + this->Self = this; + this->CheckState(); ++g_NonTrivialCount; } @@ -445,9 +447,9 @@ void TestCopyDestroy() using VariantType = vtkm::exec::internal::Variant, TypePlaceholder<1>, CountConstructDestruct, - TypePlaceholder<2>, - TypePlaceholder<3>>; -#ifndef VTKM_USING_GLIBCXX_4 + TypePlaceholder<3>, + TypePlaceholder<4>>; +#ifdef VTKM_USE_STD_IS_TRIVIAL VTKM_STATIC_ASSERT(!std::is_trivially_copyable::value); #endif // !VTKM_USING_GLIBCXX_4 vtkm::Id count = 0; @@ -547,6 +549,19 @@ void TestConstructDestruct() VTKM_TEST_ASSERT(g_NonTrivialCount == 0); } +void TestCopySelf() +{ + std::cout << "Make sure copying a Variant to itself works" << std::endl; + + using VariantType = + vtkm::exec::internal::Variant, NonTrivial, TypePlaceholder<2>>; + + VariantType variant{ NonTrivial{} }; + VariantType& variantRef = variant; + variant = variantRef; + variant = variant.Get(); +} + void RunTest() { TestSize(); @@ -557,6 +572,7 @@ void RunTest() TestCopyDestroy(); TestEmplace(); TestConstructDestruct(); + TestCopySelf(); } } // namespace test_variant diff --git a/vtkm/internal/VariantImpl.h b/vtkm/internal/VariantImpl.h index 11acef38e..e4d17a8f6 100644 --- a/vtkm/internal/VariantImpl.h +++ b/vtkm/internal/VariantImpl.h @@ -56,13 +56,47 @@ template using VariantUnionToList = typename VariantUnionToListImpl::type>::type; +struct VariantCopyConstructFunctor +{ + template + VTK_M_DEVICE void operator()(const T& src, UnionType& destUnion) const noexcept + { + constexpr vtkm::IdComponent Index = vtkm::ListIndexOf, T>::value; + // If we are using this functor, we can assume the union does not hold a valid type. + new (&VariantUnionGet(destUnion)) T(src); + } +}; + struct VariantCopyFunctor { template VTK_M_DEVICE void operator()(const T& src, UnionType& destUnion) const noexcept { constexpr vtkm::IdComponent Index = vtkm::ListIndexOf, T>::value; - new (&VariantUnionGet(destUnion)) T(src); + // If we are using this functor, we can assume the union holds type T. + this->DoCopy( + src, VariantUnionGet(destUnion), typename std::is_copy_assignable::type{}); + } + + template + VTK_M_DEVICE void DoCopy(const T& src, T& dest, std::true_type) const noexcept + { + dest = src; + } + + template + VTK_M_DEVICE void DoCopy(const T& src, T& dest, std::false_type) const noexcept + { + if (&src != &dest) + { + // Do not have an assignment operator, so destroy the old object and create a new one. + dest.~T(); + new (&dest) T(src); + } + else + { + // Objects are already the same. + } } }; @@ -228,15 +262,22 @@ struct VariantConstructorImpl, VTK_M_DEVICE VariantConstructorImpl(const VariantConstructorImpl& src) noexcept : VariantStorageImpl(vtkm::internal::NullType{}) { - src.CastAndCall(VariantCopyFunctor{}, this->Storage); + src.CastAndCall(VariantCopyConstructFunctor{}, this->Storage); this->Index = src.Index; } VTK_M_DEVICE VariantConstructorImpl& operator=(const VariantConstructorImpl& src) noexcept { - this->Reset(); - src.CastAndCall(detail::VariantCopyFunctor{}, this->Storage); - this->Index = src.Index; + if (this->GetIndex() == src.GetIndex()) + { + src.CastAndCall(detail::VariantCopyFunctor{}, this->Storage); + } + else + { + this->Reset(); + src.CastAndCall(detail::VariantCopyConstructFunctor{}, this->Storage); + this->Index = src.Index; + } return *this; } }; @@ -312,7 +353,14 @@ public: template VTK_M_DEVICE Variant& operator=(const T& src) { - this->Emplace(src); + if (this->GetIndex() == this->GetIndexOf()) + { + this->Get() = src; + } + else + { + this->Emplace(src); + } return *this; } From 9816c422b16a2a1e8e003ffe34e924508c53f65b Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 30 Mar 2021 09:01:08 -0600 Subject: [PATCH 06/11] Add padding to Grid struct in CellLocatorTwoLevel There appears to be a bug in CUDA 9.2 where if you have a class that contains a struct that itself has to have padding in the middle for alignment purposes and you then put that class in a union with other classes, it seems like that padding can cause problems with other objects in the union. --- vtkm/exec/CellLocatorTwoLevel.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vtkm/exec/CellLocatorTwoLevel.h b/vtkm/exec/CellLocatorTwoLevel.h index c774891a0..c30e4c6e4 100644 --- a/vtkm/exec/CellLocatorTwoLevel.h +++ b/vtkm/exec/CellLocatorTwoLevel.h @@ -36,6 +36,10 @@ using FloatVec3 = vtkm::Vec3f; struct Grid { DimVec3 Dimensions; + // Bug in CUDA 9.2 where having this gap for alignment was for some reason setting garbage + // in a union with other cell locators (or perhaps not properly copying data). This appears + // to be fixed by CUDA 10.2. + DimensionType Padding; FloatVec3 Origin; FloatVec3 BinSize; }; @@ -54,6 +58,7 @@ VTKM_EXEC inline vtkm::Id ComputeFlatIndex(const DimVec3& idx, const DimVec3 dim VTKM_EXEC inline Grid ComputeLeafGrid(const DimVec3& idx, const DimVec3& dim, const Grid& l1Grid) { return { dim, + 0, l1Grid.Origin + (static_cast(idx) * l1Grid.BinSize), l1Grid.BinSize / static_cast(dim) }; } From 7607736ef4b81f309fbb0ce20aa140ce45d03fec Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 30 Mar 2021 14:05:53 -0600 Subject: [PATCH 07/11] Reduce the number of lines required to implement AllTrivially* --- vtkm/internal/VariantImplDetail.h | 913 +++------------------------ vtkm/internal/VariantImplDetail.h.in | 91 +-- 2 files changed, 142 insertions(+), 862 deletions(-) diff --git a/vtkm/internal/VariantImplDetail.h b/vtkm/internal/VariantImplDetail.h index 993d8469c..e71871bd7 100644 --- a/vtkm/internal/VariantImplDetail.h +++ b/vtkm/internal/VariantImplDetail.h @@ -51,258 +51,32 @@ struct VariantDummyReturn // -------------------------------------------------------------------------------- // Helper classes to determine if all Variant types are trivial. -template +template struct AllTriviallyCopyable; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; template -struct AllTriviallyCopyable +struct AllTriviallyCopyable< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> : std::integral_constant::value && vtkmstd::is_trivially_copyable::value && vtkmstd::is_trivially_copyable::value && @@ -322,284 +96,41 @@ struct AllTriviallyCopyable::value && vtkmstd::is_trivially_copyable::value && vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - true)> { }; -template -struct AllTriviallyCopyable - : std::integral_constant::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - vtkmstd::is_trivially_copyable::value && - AllTriviallyCopyable::value)> { }; + vtkmstd::is_trivially_copyable::value)> { }; -template +template +struct AllTriviallyCopyable< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...> + : std::integral_constant::value && + AllTriviallyCopyable::value)> { }; + +template struct AllTriviallyConstructible; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; template -struct AllTriviallyConstructible +struct AllTriviallyConstructible< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> : std::integral_constant::value && vtkmstd::is_trivially_constructible::value && vtkmstd::is_trivially_constructible::value && @@ -619,284 +150,41 @@ struct AllTriviallyConstructible::value && vtkmstd::is_trivially_constructible::value && vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - true)> { }; -template -struct AllTriviallyConstructible - : std::integral_constant::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - vtkmstd::is_trivially_constructible::value && - AllTriviallyConstructible::value)> { }; + vtkmstd::is_trivially_constructible::value)> { }; -template +template +struct AllTriviallyConstructible< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...> + : std::integral_constant::value && + AllTriviallyConstructible::value)> { }; + +template struct AllTriviallyDestructible; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; -template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; template -struct AllTriviallyDestructible +struct AllTriviallyDestructible< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> : std::integral_constant::value && vtkmstd::is_trivially_destructible::value && vtkmstd::is_trivially_destructible::value && @@ -916,31 +204,14 @@ struct AllTriviallyDestructible::value && vtkmstd::is_trivially_destructible::value && vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - true)> { }; + vtkmstd::is_trivially_destructible::value)> { }; + template -struct AllTriviallyDestructible - : std::integral_constant::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - vtkmstd::is_trivially_destructible::value && - AllTriviallyDestructible::value)> { }; +struct AllTriviallyDestructible< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...> + : std::integral_constant::value && + AllTriviallyDestructible::value)> { }; // -------------------------------------------------------------------------------- // Union type used inside of Variant diff --git a/vtkm/internal/VariantImplDetail.h.in b/vtkm/internal/VariantImplDetail.h.in index 34e43465c..b69c29f1b 100644 --- a/vtkm/internal/VariantImplDetail.h.in +++ b/vtkm/internal/VariantImplDetail.h.in @@ -84,65 +84,74 @@ struct VariantDummyReturn // -------------------------------------------------------------------------------- // Helper classes to determine if all Variant types are trivial. -template +template struct AllTriviallyCopyable; -$for(num_params in range(max_expanded))\ -template <$typename_list(num_params)> -struct AllTriviallyCopyable<$type_list(num_params)> +template <$typename_list(max_expanded - 1)> +struct AllTriviallyCopyable< + $type_list(max_expanded - 1)> : std::integral_constant::value && -$for(param_index in range(1, num_params + 1))\ +$for(param_index in range(1, max_expanded - 1))\ vtkmstd::is_trivially_copyable::value && $endfor\ - true)> { }; -$endfor\ -template <$typename_list(max_expanded), typename... Ts> -struct AllTriviallyCopyable<$type_list(max_expanded), Ts...> - : std::integral_constant::value && -$for(param_index in range(1, max_expanded))\ - vtkmstd::is_trivially_copyable::value && -$endfor\ - AllTriviallyCopyable::value)> { }; + vtkmstd::is_trivially_copyable::value)> { }; -template +template <$typename_list(max_expanded), typename... Ts> +struct AllTriviallyCopyable< + $type_list(max_expanded), Ts...> + : std::integral_constant::value && + AllTriviallyCopyable::value)> { }; + +template struct AllTriviallyConstructible; -$for(num_params in range(max_expanded))\ -template <$typename_list(num_params)> -struct AllTriviallyConstructible<$type_list(num_params)> +template <$typename_list(max_expanded - 1)> +struct AllTriviallyConstructible< + $type_list(max_expanded - 1)> : std::integral_constant::value && -$for(param_index in range(1, num_params + 1))\ +$for(param_index in range(1, max_expanded - 1))\ vtkmstd::is_trivially_constructible::value && $endfor\ - true)> { }; -$endfor\ -template <$typename_list(max_expanded), typename... Ts> -struct AllTriviallyConstructible<$type_list(max_expanded), Ts...> - : std::integral_constant::value && -$for(param_index in range(1, max_expanded))\ - vtkmstd::is_trivially_constructible::value && -$endfor\ - AllTriviallyConstructible::value)> { }; + vtkmstd::is_trivially_constructible::value)> { }; -template +template <$typename_list(max_expanded), typename... Ts> +struct AllTriviallyConstructible< + $type_list(max_expanded), Ts...> + : std::integral_constant::value && + AllTriviallyConstructible::value)> { }; + +template struct AllTriviallyDestructible; -$for(num_params in range(max_expanded))\ -template <$typename_list(num_params)> -struct AllTriviallyDestructible<$type_list(num_params)> +template <$typename_list(max_expanded - 1)> +struct AllTriviallyDestructible< + $type_list(max_expanded - 1)> : std::integral_constant::value && -$for(param_index in range(1, num_params + 1))\ +$for(param_index in range(1, max_expanded - 1))\ vtkmstd::is_trivially_destructible::value && $endfor\ - true)> { }; -$endfor\ + vtkmstd::is_trivially_destructible::value)> { }; + template <$typename_list(max_expanded), typename... Ts> -struct AllTriviallyDestructible<$type_list(max_expanded), Ts...> - : std::integral_constant::value && -$for(param_index in range(1, max_expanded))\ - vtkmstd::is_trivially_destructible::value && -$endfor\ - AllTriviallyDestructible::value)> { }; +struct AllTriviallyDestructible< + $type_list(max_expanded), Ts...> + : std::integral_constant::value && + AllTriviallyDestructible::value)> { }; // -------------------------------------------------------------------------------- // Union type used inside of Variant From 991eeba9f33a807145d32d5c857ca88ed612b031 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 30 Mar 2021 14:35:44 -0600 Subject: [PATCH 08/11] Reduce the number of lines required to implement VariantUnion --- vtkm/internal/VariantImplDetail.h | 732 ++------------------------- vtkm/internal/VariantImplDetail.h.in | 49 +- 2 files changed, 78 insertions(+), 703 deletions(-) diff --git a/vtkm/internal/VariantImplDetail.h b/vtkm/internal/VariantImplDetail.h index e71871bd7..0c00a9a58 100644 --- a/vtkm/internal/VariantImplDetail.h +++ b/vtkm/internal/VariantImplDetail.h @@ -75,8 +75,7 @@ template -struct AllTriviallyCopyable< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> +struct AllTriviallyCopyable : std::integral_constant::value && vtkmstd::is_trivially_copyable::value && vtkmstd::is_trivially_copyable::value && @@ -99,8 +98,7 @@ struct AllTriviallyCopyable< vtkmstd::is_trivially_copyable::value)> { }; template -struct AllTriviallyCopyable< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...> +struct AllTriviallyCopyable : std::integral_constant::value && AllTriviallyCopyable::value)> { }; @@ -129,8 +127,7 @@ template -struct AllTriviallyConstructible< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> +struct AllTriviallyConstructible : std::integral_constant::value && vtkmstd::is_trivially_constructible::value && vtkmstd::is_trivially_constructible::value && @@ -153,8 +150,7 @@ struct AllTriviallyConstructible< vtkmstd::is_trivially_constructible::value)> { }; template -struct AllTriviallyConstructible< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...> +struct AllTriviallyConstructible : std::integral_constant::value && AllTriviallyConstructible::value)> { }; @@ -183,8 +179,7 @@ template -struct AllTriviallyDestructible< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> +struct AllTriviallyDestructible : std::integral_constant::value && vtkmstd::is_trivially_destructible::value && vtkmstd::is_trivially_destructible::value && @@ -207,8 +202,7 @@ struct AllTriviallyDestructible< vtkmstd::is_trivially_destructible::value)> { }; template -struct AllTriviallyDestructible< - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...> +struct AllTriviallyDestructible : std::integral_constant::value && AllTriviallyDestructible::value)> { }; @@ -242,678 +236,53 @@ struct AllTriviallyDestructible< // // TD = trivially deconstructible -template +template union VariantUnionTD; // NTD = non-trivially deconstructible -template +template union VariantUnionNTD; -template -union VariantUnionTD -{ - T0 V0; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - T16 V16; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - T16 V16; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - T16 V16; - T17 V17; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - T16 V16; - T17 V17; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - -template -union VariantUnionTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - T16 V16; - T17 V17; - T18 V18; - VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } - VariantUnionTD() = default; -}; - -template -union VariantUnionNTD -{ - T0 V0; - T1 V1; - T2 V2; - T3 V3; - T4 V4; - T5 V5; - T6 V6; - T7 V7; - T8 V8; - T9 V9; - T10 V10; - T11 V11; - T12 V12; - T13 V13; - T14 V14; - T15 V15; - T16 V16; - T17 V17; - T18 V18; - VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } - VariantUnionNTD() = default; - VTK_M_DEVICE ~VariantUnionNTD() { } -}; - template union VariantUnionTD { @@ -937,6 +306,7 @@ union VariantUnionTD union VariantUnionTD { @@ -995,6 +365,7 @@ union VariantUnionTD Remaining; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } VariantUnionTD() = default; }; @@ -1024,6 +395,7 @@ union VariantUnionNTD Remaining; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } VariantUnionNTD() = default; VTK_M_DEVICE ~VariantUnionNTD() { } diff --git a/vtkm/internal/VariantImplDetail.h.in b/vtkm/internal/VariantImplDetail.h.in index b69c29f1b..4942d931a 100644 --- a/vtkm/internal/VariantImplDetail.h.in +++ b/vtkm/internal/VariantImplDetail.h.in @@ -92,8 +92,7 @@ $endfor\ struct AllTriviallyCopyable; template <$typename_list(max_expanded - 1)> -struct AllTriviallyCopyable< - $type_list(max_expanded - 1)> +struct AllTriviallyCopyable<$type_list(max_expanded - 1)> : std::integral_constant::value && $for(param_index in range(1, max_expanded - 1))\ vtkmstd::is_trivially_copyable::value && @@ -101,8 +100,7 @@ $endfor\ vtkmstd::is_trivially_copyable::value)> { }; template <$typename_list(max_expanded), typename... Ts> -struct AllTriviallyCopyable< - $type_list(max_expanded), Ts...> +struct AllTriviallyCopyable<$type_list(max_expanded), Ts...> : std::integral_constant::value && AllTriviallyCopyable::value)> { }; @@ -115,8 +113,7 @@ $endfor\ struct AllTriviallyConstructible; template <$typename_list(max_expanded - 1)> -struct AllTriviallyConstructible< - $type_list(max_expanded - 1)> +struct AllTriviallyConstructible<$type_list(max_expanded - 1)> : std::integral_constant::value && $for(param_index in range(1, max_expanded - 1))\ vtkmstd::is_trivially_constructible::value && @@ -124,8 +121,7 @@ $endfor\ vtkmstd::is_trivially_constructible::value)> { }; template <$typename_list(max_expanded), typename... Ts> -struct AllTriviallyConstructible< - $type_list(max_expanded), Ts...> +struct AllTriviallyConstructible<$type_list(max_expanded), Ts...> : std::integral_constant::value && AllTriviallyConstructible::value)> { }; @@ -138,8 +134,7 @@ $endfor\ struct AllTriviallyDestructible; template <$typename_list(max_expanded - 1)> -struct AllTriviallyDestructible< - $type_list(max_expanded - 1)> +struct AllTriviallyDestructible<$type_list(max_expanded - 1)> : std::integral_constant::value && $for(param_index in range(1, max_expanded - 1))\ vtkmstd::is_trivially_destructible::value && @@ -147,8 +142,7 @@ $endfor\ vtkmstd::is_trivially_destructible::value)> { }; template <$typename_list(max_expanded), typename... Ts> -struct AllTriviallyDestructible< - $type_list(max_expanded), Ts...> +struct AllTriviallyDestructible<$type_list(max_expanded), Ts...> : std::integral_constant::value && AllTriviallyDestructible::value)> { }; @@ -182,37 +176,44 @@ struct AllTriviallyDestructible< // // TD = trivially deconstructible -template +template union VariantUnionTD; // NTD = non-trivially deconstructible -template +template union VariantUnionNTD; -$for(num_params in range(max_expanded))\ -template <$typename_list(num_params)> -union VariantUnionTD<$type_list(num_params)> +template <$typename_list(max_expanded - 1)> +union VariantUnionTD<$type_list(max_expanded - 1)> { -$for(param_index in range(num_params + 1))\ +$for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } VariantUnionTD() = default; }; -template <$typename_list(num_params)> -union VariantUnionNTD<$type_list(num_params)> +template <$typename_list(max_expanded - 1)> +union VariantUnionNTD<$type_list(max_expanded - 1)> { -$for(param_index in range(num_params + 1))\ +$for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } VariantUnionNTD() = default; VTK_M_DEVICE ~VariantUnionNTD() { } }; -$endfor\ - template <$typename_list(max_expanded), typename... Ts> union VariantUnionTD<$type_list(max_expanded), Ts...> { @@ -221,6 +222,7 @@ $for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ VariantUnionTD Remaining; + VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } VariantUnionTD() = default; }; @@ -233,6 +235,7 @@ $for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ VariantUnionNTD Remaining; + VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } VariantUnionNTD() = default; VTK_M_DEVICE ~VariantUnionNTD() { } From 647bc94fed9abbff2833ef64dda9c511d2db2c0f Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 30 Mar 2021 15:22:38 -0600 Subject: [PATCH 09/11] Reduce the number of lines required to implement Variant::CastAndCall --- vtkm/internal/VariantImpl.h | 26 +- vtkm/internal/VariantImplDetail.h | 1063 +++++--------------------- vtkm/internal/VariantImplDetail.h.in | 111 ++- 3 files changed, 261 insertions(+), 939 deletions(-) diff --git a/vtkm/internal/VariantImpl.h b/vtkm/internal/VariantImpl.h index e4d17a8f6..90afb3807 100644 --- a/vtkm/internal/VariantImpl.h +++ b/vtkm/internal/VariantImpl.h @@ -179,11 +179,8 @@ struct VariantStorageImpl -> decltype(f(std::declval&>(), args...)) { VTKM_ASSERT(this->IsValid()); - return detail::VariantCastAndCallImpl(vtkm::ListSize>{}, - this->GetIndex(), - std::forward(f), - this->Storage, - std::forward(args)...); + return detail::VariantCastAndCallImpl( + this->GetIndex(), std::forward(f), this->Storage, std::forward(args)...); } template @@ -192,11 +189,8 @@ struct VariantStorageImpl -> decltype(f(std::declval&>(), args...)) { VTKM_ASSERT(this->IsValid()); - return detail::VariantCastAndCallImpl(vtkm::ListSize>{}, - this->GetIndex(), - std::forward(f), - this->Storage, - std::forward(args)...); + return detail::VariantCastAndCallImpl( + this->GetIndex(), std::forward(f), this->Storage, std::forward(args)...); } }; @@ -466,11 +460,7 @@ public: { VTKM_ASSERT(this->IsValid()); return detail::VariantCastAndCallImpl( - std::integral_constant{}, - this->GetIndex(), - std::forward(f), - this->Storage, - std::forward(args)...); + this->GetIndex(), std::forward(f), this->Storage, std::forward(args)...); } template @@ -480,11 +470,7 @@ public: { VTKM_ASSERT(this->IsValid()); return detail::VariantCastAndCallImpl( - std::integral_constant{}, - this->GetIndex(), - std::forward(f), - this->Storage, - std::forward(args)...); + this->GetIndex(), std::forward(f), this->Storage, std::forward(args)...); } /// Destroys any object the Variant is holding and sets the Variant to an invalid state. This diff --git a/vtkm/internal/VariantImplDetail.h b/vtkm/internal/VariantImplDetail.h index 0c00a9a58..6e9bc3c2b 100644 --- a/vtkm/internal/VariantImplDetail.h +++ b/vtkm/internal/VariantImplDetail.h @@ -306,6 +306,7 @@ union VariantUnionTD union VariantUnionTD { - vtkm::internal::NullType Dummy; T0 V0; T1 V1; T2 V2; @@ -373,7 +374,6 @@ union VariantUnionTD union VariantUnionNTD { - vtkm::internal::NullType Dummy; T0 V0; T1 V1; T2 V2; @@ -728,892 +728,201 @@ VTK_M_DEVICE auto VariantUnionGet(UnionType& storage) noexcept return VariantUnionGetImpl::type>::Get(storage); } -// -------------------------------------------------------------------------------- -// Internal implementation of CastAndCall for Variant -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - case 14: - return f(storage.V14, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - case 14: - return f(storage.V14, std::forward(args)...); - case 15: - return f(storage.V15, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - case 14: - return f(storage.V14, std::forward(args)...); - case 15: - return f(storage.V15, std::forward(args)...); - case 16: - return f(storage.V16, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - case 14: - return f(storage.V14, std::forward(args)...); - case 15: - return f(storage.V15, std::forward(args)...); - case 16: - return f(storage.V16, std::forward(args)...); - case 17: - return f(storage.V17, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - case 14: - return f(storage.V14, std::forward(args)...); - case 15: - return f(storage.V15, std::forward(args)...); - case 16: - return f(storage.V16, std::forward(args)...); - case 17: - return f(storage.V17, std::forward(args)...); - case 18: - return f(storage.V18, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - case 14: - return f(storage.V14, std::forward(args)...); - case 15: - return f(storage.V15, std::forward(args)...); - case 16: - return f(storage.V16, std::forward(args)...); - case 17: - return f(storage.V17, std::forward(args)...); - case 18: - return f(storage.V18, std::forward(args)...); - case 19: - return f(storage.V19, std::forward(args)...); - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - //clang-format on -// Recurse for cases where Variant has more than 20 types -template +VTK_M_DEVICE inline ReturnType VariantCallFunctor( + std::false_type, + Functor&& f, + CastMember& value, + Args&&... args) noexcept(noexcept(f(value, args...))) +{ + // If you get a compile error here, it probably means that you have called Variant::CastAndCall + // with a functor that does not accept one of the types in the Variant. The functor you provide + // must be callable with all types in the Variant, not just the one that it currently holds. + return f(value, std::forward(args)...); +} + +template +VTK_M_DEVICE inline ReturnType VariantCallFunctor( + std::true_type, Functor&&, vtkm::internal::NullType, Args&&...) noexcept +{ + // If we are here, it means a Variant had an inappropriate index. + VTKM_ASSERT(false && "Internal error, bad Variant state."); + return VariantDummyReturn::F(); +} + +// Terminating condition in recursive template +template +VTK_M_DEVICE inline ReturnType VariantCastAndCallImplR( + std::true_type, + vtkm::IdComponent vtkmNotUsed(index), + Functor&& vtkmNotUsed(f), + vtkm::internal::NullType, + Args&&... vtkmNotUsed(args)) noexcept +{ + // If we are here, it means a Variant had an inappropriate index. + VTKM_ASSERT(false && "Internal error, bad Variant state."); + return VariantDummyReturn::F(); +} + +template +VTK_M_DEVICE inline ReturnType VariantCastAndCallImplR( + std::false_type, + vtkm::IdComponent index, + Functor&& f, + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) +{ + switch (index) + { + case 0: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V0, + std::forward(args)...); + case 1: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V1, + std::forward(args)...); + case 2: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V2, + std::forward(args)...); + case 3: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V3, + std::forward(args)...); + case 4: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V4, + std::forward(args)...); + case 5: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V5, + std::forward(args)...); + case 6: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V6, + std::forward(args)...); + case 7: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V7, + std::forward(args)...); + case 8: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V8, + std::forward(args)...); + case 9: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V9, + std::forward(args)...); + case 10: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V10, + std::forward(args)...); + case 11: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V11, + std::forward(args)...); + case 12: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V12, + std::forward(args)...); + case 13: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V13, + std::forward(args)...); + case 14: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V14, + std::forward(args)...); + case 15: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V15, + std::forward(args)...); + case 16: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V16, + std::forward(args)...); + case 17: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V17, + std::forward(args)...); + case 18: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V18, + std::forward(args)...); + case 19: + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V19, + std::forward(args)...); + default: + return VariantCastAndCallImplR( + typename std::is_same::type{}, + index - 20, + std::forward(f), + storage.Remaining, + std::forward(args)...); + } +} + +template VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, vtkm::IdComponent index, Functor&& f, UnionType& storage, Args&&... args) noexcept(noexcept(f(storage.V0, args...))) -> decltype(f(storage.V0, args...)) { - switch (index) - { - case 0: - return f(storage.V0, std::forward(args)...); - case 1: - return f(storage.V1, std::forward(args)...); - case 2: - return f(storage.V2, std::forward(args)...); - case 3: - return f(storage.V3, std::forward(args)...); - case 4: - return f(storage.V4, std::forward(args)...); - case 5: - return f(storage.V5, std::forward(args)...); - case 6: - return f(storage.V6, std::forward(args)...); - case 7: - return f(storage.V7, std::forward(args)...); - case 8: - return f(storage.V8, std::forward(args)...); - case 9: - return f(storage.V9, std::forward(args)...); - case 10: - return f(storage.V10, std::forward(args)...); - case 11: - return f(storage.V11, std::forward(args)...); - case 12: - return f(storage.V12, std::forward(args)...); - case 13: - return f(storage.V13, std::forward(args)...); - case 14: - return f(storage.V14, std::forward(args)...); - case 15: - return f(storage.V15, std::forward(args)...); - case 16: - return f(storage.V16, std::forward(args)...); - case 17: - return f(storage.V17, std::forward(args)...); - case 18: - return f(storage.V18, std::forward(args)...); - case 19: - return f(storage.V19, std::forward(args)...); - default: - return VariantCastAndCallImpl(std::integral_constant{}, - index - 20, - std::forward(f), - storage.Remaining, - std::forward(args)...); - } + return VariantCastAndCallImplR( + std::false_type{}, index, std::forward(f), storage, std::forward(args)...); } } diff --git a/vtkm/internal/VariantImplDetail.h.in b/vtkm/internal/VariantImplDetail.h.in index 4942d931a..39587939e 100644 --- a/vtkm/internal/VariantImplDetail.h.in +++ b/vtkm/internal/VariantImplDetail.h.in @@ -197,6 +197,7 @@ union VariantUnionTD<$type_list(max_expanded - 1)> $for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ + vtkm::internal::NullType Remaining; VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { } VariantUnionTD() = default; @@ -208,6 +209,7 @@ union VariantUnionNTD<$type_list(max_expanded - 1)> $for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ + vtkm::internal::NullType Remaining; VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { } VariantUnionNTD() = default; @@ -217,7 +219,6 @@ $endfor\ template <$typename_list(max_expanded), typename... Ts> union VariantUnionTD<$type_list(max_expanded), Ts...> { - vtkm::internal::NullType Dummy; $for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ @@ -230,7 +231,6 @@ $endfor\ template <$typename_list(max_expanded), typename... Ts> union VariantUnionNTD<$type_list(max_expanded), Ts...> { - vtkm::internal::NullType Dummy; $for(param_index in range(max_expanded))\ T$(param_index) V$(param_index); $endfor\ @@ -304,64 +304,91 @@ VTK_M_DEVICE auto VariantUnionGet(UnionType& storage) noexcept return VariantUnionGetImpl::type>::Get(storage); } -// -------------------------------------------------------------------------------- -// Internal implementation of CastAndCall for Variant -$for(num_params in range(max_expanded))\ -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, - vtkm::IdComponent index, - Functor&& f, - UnionType& storage, - Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) -{ - switch (index) - { -$for(param_index in range(num_params + 1))\ - case $(param_index): - return f(storage.V$(param_index), std::forward(args)...); -$endfor\ - default: - // If we are here, it means we failed to find the appropriate type in a variant - VTKM_ASSERT(false && "Internal error, bad Variant state."); - return VariantDummyReturn::F(); - } -} - -$endfor\ //clang-format on -// Recurse for cases where Variant has more than $(max_expanded) types -template -VTK_M_DEVICE inline auto VariantCastAndCallImpl( - std::integral_constant, +VTK_M_DEVICE inline ReturnType VariantCallFunctor( + std::false_type, + Functor&& f, + CastMember& value, + Args&&... args) noexcept(noexcept(f(value, args...))) +{ + // If you get a compile error here, it probably means that you have called Variant::CastAndCall + // with a functor that does not accept one of the types in the Variant. The functor you provide + // must be callable with all types in the Variant, not just the one that it currently holds. + return f(value, std::forward(args)...); +} + +template +VTK_M_DEVICE inline ReturnType VariantCallFunctor( + std::true_type, Functor&&, vtkm::internal::NullType, Args&&...) noexcept +{ + // If we are here, it means a Variant had an inappropriate index. + VTKM_ASSERT(false && "Internal error, bad Variant state."); + return VariantDummyReturn::F(); +} + +// Terminating condition in recursive template +template +VTK_M_DEVICE inline ReturnType VariantCastAndCallImplR( + std::true_type, + vtkm::IdComponent vtkmNotUsed(index), + Functor&& vtkmNotUsed(f), + vtkm::internal::NullType, + Args&&... vtkmNotUsed(args)) noexcept +{ + // If we are here, it means a Variant had an inappropriate index. + VTKM_ASSERT(false && "Internal error, bad Variant state."); + return VariantDummyReturn::F(); +} + +template +VTK_M_DEVICE inline ReturnType VariantCastAndCallImplR( + std::false_type, vtkm::IdComponent index, Functor&& f, UnionType& storage, Args&&... args) noexcept(noexcept(f(storage.V0, args...))) - -> decltype(f(storage.V0, args...)) { switch (index) { $for(param_index in range(max_expanded))\ case $(param_index): - return f(storage.V$(param_index), std::forward(args)...); + return VariantCallFunctor( + typename std::is_same::type{}, + std::forward(f), + storage.V$(param_index), + std::forward(args)...); $endfor\ default: - return VariantCastAndCallImpl(std::integral_constant{}, - index - $(max_expanded), - std::forward(f), - storage.Remaining, - std::forward(args)...); + return VariantCastAndCallImplR( + typename std::is_same::type{}, + index - $(max_expanded), + std::forward(f), + storage.Remaining, + std::forward(args)...); } } +template +VTK_M_DEVICE inline auto VariantCastAndCallImpl( + vtkm::IdComponent index, + Functor&& f, + UnionType& storage, + Args&&... args) noexcept(noexcept(f(storage.V0, args...))) + -> decltype(f(storage.V0, args...)) +{ + return VariantCastAndCallImplR( + std::false_type{}, index, std::forward(f), storage, std::forward(args)...); +} + } } } From 6ccb32d27b6576315968d01b1f6ab65466d650b9 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Wed, 31 Mar 2021 14:35:06 -0600 Subject: [PATCH 10/11] Slight comment changes --- vtkm/internal/VariantImplDetail.h | 12 +++++++----- vtkm/internal/VariantImplDetail.h.in | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/vtkm/internal/VariantImplDetail.h b/vtkm/internal/VariantImplDetail.h index 6e9bc3c2b..57a591d2f 100644 --- a/vtkm/internal/VariantImplDetail.h +++ b/vtkm/internal/VariantImplDetail.h @@ -216,16 +216,18 @@ struct AllTriviallyDestructible // reinterpret_cast. However, doing that leads to undefined behavior. The C++ compiler assumes that // 2 pointers of different types point to different memory (even if it is clear that they are set // to the same address). That means optimizers can remove code because it "knows" that data in one -// type cannot affect data in another type. To safely change the type of an std::aligned_union, -// you really have to do an std::memcpy. This is problematic for types that cannot be trivially -// copied. Another problem is that we found that device compilers do not optimize the memcpy -// as well as most CPU compilers. Likely, memcpy is used much less frequently on GPU devices. +// type cannot affect data in another type. (See Shafik Yaghmour's excellent writeup at +// https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8 for more details.) To safely +// change the type of an std::aligned_union, you really have to do an std::memcpy. This is +// problematic for types that cannot be trivially copied. Another problem is that we found that +// device compilers do not optimize the memcpy as well as most CPU compilers. Likely, memcpy is +// used much less frequently on GPU devices. // // Part of the trickiness of the union implementation is trying to preserve when the type is // trivially constructible and copyable. The trick is that if members of the union are not trivial, // then the default constructors are deleted. To get around that, a non-default constructor is // added, which we can use to construct the union for non-trivial types. Working with types with -// non-trivial destructors are particularly trick. Again, if any member of the union has a +// non-trivial destructors are particularly tricky. Again, if any member of the union has a // non-trivial destructor, the destructor is deleted. Unlike a constructor, you cannot just say to // use a different destructor. Thus, we have to define our own destructor for the union. // Technically, the destructor here does not do anything, but the actual destruction should be From 6921b5cc3d17b4abbc351b8fe487614ddb36947d Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Thu, 1 Apr 2021 14:47:51 -0600 Subject: [PATCH 11/11] Minor style changes in UnitTestVariant --- .../exec/internal/testing/UnitTestVariant.cxx | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/vtkm/exec/internal/testing/UnitTestVariant.cxx b/vtkm/exec/internal/testing/UnitTestVariant.cxx index fd3040968..83d645764 100644 --- a/vtkm/exec/internal/testing/UnitTestVariant.cxx +++ b/vtkm/exec/internal/testing/UnitTestVariant.cxx @@ -236,18 +236,18 @@ void TestTriviallyCopyable() { #ifdef VTKM_USE_STD_IS_TRIVIAL // Make sure base types are behaving as expected - VTKM_STATIC_ASSERT(std::is_trivially_constructible::value); - VTKM_STATIC_ASSERT(std::is_trivially_copyable::value); - VTKM_STATIC_ASSERT(std::is_trivial::value); - VTKM_STATIC_ASSERT(std::is_trivially_constructible::value); - VTKM_STATIC_ASSERT(std::is_trivially_copyable::value); - VTKM_STATIC_ASSERT(std::is_trivial::value); - VTKM_STATIC_ASSERT(!std::is_trivially_constructible::value); - VTKM_STATIC_ASSERT(!std::is_trivially_copyable::value); - VTKM_STATIC_ASSERT(!std::is_trivial::value); - VTKM_STATIC_ASSERT(!std::is_trivially_constructible::value); - VTKM_STATIC_ASSERT(std::is_trivially_copyable::value); - VTKM_STATIC_ASSERT(!std::is_trivial::value); + VTKM_STATIC_ASSERT(vtkmstd::is_trivially_constructible::value); + VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable::value); + VTKM_STATIC_ASSERT(vtkmstd::is_trivial::value); + VTKM_STATIC_ASSERT(vtkmstd::is_trivially_constructible::value); + VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable::value); + VTKM_STATIC_ASSERT(vtkmstd::is_trivial::value); + VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_constructible::value); + VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_copyable::value); + VTKM_STATIC_ASSERT(!vtkmstd::is_trivial::value); + VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_constructible::value); + VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable::value); + VTKM_STATIC_ASSERT(!vtkmstd::is_trivial::value); // A variant of trivially constructable things should be trivially constructable VTKM_STATIC_ASSERT((vtkmstd::is_trivially_constructible< @@ -295,7 +295,7 @@ void TestTriviallyCopyable() (!vtkmstd::is_trivial>::value)); VTKM_STATIC_ASSERT( (!vtkmstd::is_trivial>::value)); -#endif // !VTKM_USING_GLIBCXX_4 +#endif // VTKM_USE_STD_IS_TRIVIAL } struct TestFunctor @@ -450,8 +450,8 @@ void TestCopyDestroy() TypePlaceholder<3>, TypePlaceholder<4>>; #ifdef VTKM_USE_STD_IS_TRIVIAL - VTKM_STATIC_ASSERT(!std::is_trivially_copyable::value); -#endif // !VTKM_USING_GLIBCXX_4 + VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_copyable::value); +#endif // VTKM_USE_STD_IS_TRIVIAL vtkm::Id count = 0; VariantType variant1 = CountConstructDestruct(&count);