Commit 2bd4805f authored by Kenneth Moreland's avatar Kenneth Moreland Committed by Kitware Robot
Browse files

Merge topic 'variant-safe-punning2'

6921b5cc Minor style changes in UnitTestVariant
6ccb32d2 Slight comment changes
647bc94f Reduce the number of lines required to implement Variant::CastAndCall
991eeba9 Reduce the number of lines required to implement VariantUnion
7607736e Reduce the number of lines required to implement AllTrivially*
9816c422 Add padding to Grid struct in CellLocatorTwoLevel
e480fd7a Support copying a Variant to itself
d2d9ba33

 Make connectivity structures trivially copyable
...
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !2444
parents 46c2af29 6921b5cc
......@@ -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<FloatVec3>(idx) * l1Grid.BinSize),
l1Grid.BinSize / static_cast<FloatVec3>(dim) };
}
......
......@@ -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;
......
......@@ -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(
......
......@@ -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;
}
......@@ -234,65 +236,66 @@ void TestTriviallyCopyable()
{
#ifdef VTKM_USE_STD_IS_TRIVIAL
// Make sure base types are behaving as expected
VTKM_STATIC_ASSERT(std::is_trivially_constructible<float>::value);
VTKM_STATIC_ASSERT(std::is_trivially_copyable<float>::value);
VTKM_STATIC_ASSERT(std::is_trivial<float>::value);
VTKM_STATIC_ASSERT(std::is_trivially_constructible<int>::value);
VTKM_STATIC_ASSERT(std::is_trivially_copyable<int>::value);
VTKM_STATIC_ASSERT(std::is_trivial<int>::value);
VTKM_STATIC_ASSERT(!std::is_trivially_constructible<NonTrivial>::value);
VTKM_STATIC_ASSERT(!std::is_trivially_copyable<NonTrivial>::value);
VTKM_STATIC_ASSERT(!std::is_trivial<NonTrivial>::value);
VTKM_STATIC_ASSERT(!std::is_trivially_constructible<TrivialCopy>::value);
VTKM_STATIC_ASSERT(std::is_trivially_copyable<TrivialCopy>::value);
VTKM_STATIC_ASSERT(!std::is_trivial<TrivialCopy>::value);
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_constructible<float>::value);
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable<float>::value);
VTKM_STATIC_ASSERT(vtkmstd::is_trivial<float>::value);
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_constructible<int>::value);
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable<int>::value);
VTKM_STATIC_ASSERT(vtkmstd::is_trivial<int>::value);
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_constructible<NonTrivial>::value);
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_copyable<NonTrivial>::value);
VTKM_STATIC_ASSERT(!vtkmstd::is_trivial<NonTrivial>::value);
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_constructible<TrivialCopy>::value);
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable<TrivialCopy>::value);
VTKM_STATIC_ASSERT(!vtkmstd::is_trivial<TrivialCopy>::value);
// A variant of trivially constructable things should be trivially constructable
VTKM_STATIC_ASSERT((vtkm::exec::internal::detail::AllTriviallyConstructible<float, int>::value));
VTKM_STATIC_ASSERT((vtkmstd::is_trivially_constructible<
vtkm::exec::internal::detail::VariantUnion<float, int>>::value));
VTKM_STATIC_ASSERT(
(std::is_trivially_constructible<vtkm::exec::internal::Variant<float, int>>::value));
(vtkmstd::is_trivially_constructible<vtkm::exec::internal::Variant<float, int>>::value));
// A variant of trivially copyable things should be trivially copyable
VTKM_STATIC_ASSERT(
(vtkm::exec::internal::detail::AllTriviallyCopyable<float, int, TrivialCopy>::value));
VTKM_STATIC_ASSERT(
(std::is_trivially_copyable<vtkm::exec::internal::Variant<float, int, TrivialCopy>>::value));
VTKM_STATIC_ASSERT((vtkmstd::is_trivially_copyable<
vtkm::exec::internal::detail::VariantUnion<float, int, TrivialCopy>>::value));
VTKM_STATIC_ASSERT((
vtkmstd::is_trivially_copyable<vtkm::exec::internal::Variant<float, int, TrivialCopy>>::value));
// A variant of any non-trivially constructable things is not trivially copyable
VTKM_STATIC_ASSERT(
(!vtkm::exec::internal::detail::AllTriviallyConstructible<NonTrivial, float, int>::value));
VTKM_STATIC_ASSERT(
(!vtkm::exec::internal::detail::AllTriviallyConstructible<float, NonTrivial, int>::value));
VTKM_STATIC_ASSERT(
(!vtkm::exec::internal::detail::AllTriviallyConstructible<float, int, NonTrivial>::value));
VTKM_STATIC_ASSERT((!std::is_trivially_constructible<
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
vtkm::exec::internal::detail::VariantUnion<NonTrivial, float, int>>::value));
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
vtkm::exec::internal::detail::VariantUnion<float, NonTrivial, int>>::value));
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
vtkm::exec::internal::detail::VariantUnion<float, int, NonTrivial>>::value));
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
vtkm::exec::internal::Variant<NonTrivial, float, int>>::value));
VTKM_STATIC_ASSERT((!std::is_trivially_constructible<
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
vtkm::exec::internal::Variant<float, NonTrivial, int>>::value));
VTKM_STATIC_ASSERT((!std::is_trivially_constructible<
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
vtkm::exec::internal::Variant<float, int, NonTrivial>>::value));
// A variant of any non-trivially copyable things is not trivially copyable
VTKM_STATIC_ASSERT(
(!vtkm::exec::internal::detail::AllTriviallyCopyable<NonTrivial, float, int>::value));
VTKM_STATIC_ASSERT(
(!vtkm::exec::internal::detail::AllTriviallyCopyable<float, NonTrivial, int>::value));
VTKM_STATIC_ASSERT(
(!vtkm::exec::internal::detail::AllTriviallyCopyable<float, int, NonTrivial>::value));
VTKM_STATIC_ASSERT(
(!std::is_trivially_copyable<vtkm::exec::internal::Variant<NonTrivial, float, int>>::value));
VTKM_STATIC_ASSERT(
(!std::is_trivially_copyable<vtkm::exec::internal::Variant<float, NonTrivial, int>>::value));
VTKM_STATIC_ASSERT(
(!std::is_trivially_copyable<vtkm::exec::internal::Variant<float, int, NonTrivial>>::value));
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable<
vtkm::exec::internal::detail::VariantUnion<NonTrivial, float, int>>::value));
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable<
vtkm::exec::internal::detail::VariantUnion<float, NonTrivial, int>>::value));
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable<
vtkm::exec::internal::detail::VariantUnion<float, int, NonTrivial>>::value));
VTKM_STATIC_ASSERT((
!vtkmstd::is_trivially_copyable<vtkm::exec::internal::Variant<NonTrivial, float, int>>::value));
VTKM_STATIC_ASSERT((
!vtkmstd::is_trivially_copyable<vtkm::exec::internal::Variant<float, NonTrivial, int>>::value));
VTKM_STATIC_ASSERT((
!vtkmstd::is_trivially_copyable<vtkm::exec::internal::Variant<float, int, NonTrivial>>::value));
// A variant of trivial things should be trivial
VTKM_STATIC_ASSERT((std::is_trivial<vtkm::exec::internal::Variant<float, int>>::value));
VTKM_STATIC_ASSERT((vtkmstd::is_trivial<vtkm::exec::internal::Variant<float, int>>::value));
VTKM_STATIC_ASSERT(
(!std::is_trivial<vtkm::exec::internal::Variant<float, int, TrivialCopy>>::value));
(!vtkmstd::is_trivial<vtkm::exec::internal::Variant<float, int, TrivialCopy>>::value));
VTKM_STATIC_ASSERT(
(!std::is_trivial<vtkm::exec::internal::Variant<float, int, NonTrivial>>::value));
#endif // !VTKM_USING_GLIBCXX_4
(!vtkmstd::is_trivial<vtkm::exec::internal::Variant<float, int, NonTrivial>>::value));
#endif // VTKM_USE_STD_IS_TRIVIAL
}
struct TestFunctor
......@@ -434,6 +437,7 @@ struct CountConstructDestruct
++(*this->Count);
}
~CountConstructDestruct() { --(*this->Count); }
CountConstructDestruct& operator=(const CountConstructDestruct&) = delete;
};
void TestCopyDestroy()
......@@ -443,11 +447,11 @@ void TestCopyDestroy()
using VariantType = vtkm::exec::internal::Variant<TypePlaceholder<0>,
TypePlaceholder<1>,
CountConstructDestruct,
TypePlaceholder<2>,
TypePlaceholder<3>>;
#ifndef VTKM_USING_GLIBCXX_4
VTKM_STATIC_ASSERT(!std::is_trivially_copyable<VariantType>::value);
#endif // !VTKM_USING_GLIBCXX_4
TypePlaceholder<3>,
TypePlaceholder<4>>;
#ifdef VTKM_USE_STD_IS_TRIVIAL
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_copyable<VariantType>::value);
#endif // VTKM_USE_STD_IS_TRIVIAL
vtkm::Id count = 0;
VariantType variant1 = CountConstructDestruct(&count);
......@@ -545,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<TypePlaceholder<0>, NonTrivial, TypePlaceholder<2>>;
VariantType variant{ NonTrivial{} };
VariantType& variantRef = variant;
variant = variantRef;
variant = variant.Get<NonTrivial>();
}
void RunTest()
{
TestSize();
......@@ -555,6 +572,7 @@ void RunTest()
TestCopyDestroy();
TestEmplace();
TestConstructDestruct();
TestCopySelf();
}
} // namespace test_variant
......
......@@ -20,8 +20,7 @@
#include <vtkm/Deprecated.h>
#include <vtkm/List.h>
#include <vtkmstd/aligned_union.h>
#include <vtkmstd/is_trivial.h>
#include <vtkm/internal/Assume.h>
namespace vtkm
{
......@@ -37,12 +36,67 @@ class Variant;
namespace detail
{
// --------------------------------------------------------------------------------
// Helper classes for Variant
template <typename UnionType>
struct VariantUnionToListImpl;
template <typename... Ts>
struct VariantUnionToListImpl<detail::VariantUnionTD<Ts...>>
{
using type = vtkm::List<Ts...>;
};
template <typename... Ts>
struct VariantUnionToListImpl<detail::VariantUnionNTD<Ts...>>
{
using type = vtkm::List<Ts...>;
};
template <typename UnionType>
using VariantUnionToList =
typename VariantUnionToListImpl<typename std::decay<UnionType>::type>::type;
struct VariantCopyConstructFunctor
{
template <typename T, typename UnionType>
VTK_M_DEVICE void operator()(const T& src, UnionType& destUnion) const noexcept
{
constexpr vtkm::IdComponent Index = vtkm::ListIndexOf<VariantUnionToList<UnionType>, T>::value;
// If we are using this functor, we can assume the union does not hold a valid type.
new (&VariantUnionGet<Index>(destUnion)) T(src);
}
};
struct VariantCopyFunctor
{
template <typename T, typename UnionType>
VTK_M_DEVICE void operator()(const T& src, UnionType& destUnion) const noexcept
{
constexpr vtkm::IdComponent Index = vtkm::ListIndexOf<VariantUnionToList<UnionType>, T>::value;
// If we are using this functor, we can assume the union holds type T.
this->DoCopy(
src, VariantUnionGet<Index>(destUnion), typename std::is_copy_assignable<T>::type{});
}
template <typename T>
VTK_M_DEVICE void operator()(const T& src, void* destPointer) const noexcept
VTK_M_DEVICE void DoCopy(const T& src, T& dest, std::true_type) const noexcept
{
new (destPointer) T(src);
dest = src;
}
template <typename T>
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.
}
}
};
......@@ -68,56 +122,6 @@ struct VariantCheckType
VTKM_STATIC_ASSERT_MSG(!std::is_pointer<T>::value, "Pointers are not allowed in VTK-m Variant.");
};
template <typename... Ts>
struct AllTriviallyCopyable;
template <>
struct AllTriviallyCopyable<> : std::true_type
{
};
template <typename T0>
struct AllTriviallyCopyable<T0>
: std::integral_constant<bool, (vtkmstd::is_trivially_copyable<T0>::value)>
{
};
template <typename T0, typename T1>
struct AllTriviallyCopyable<T0, T1>
: std::integral_constant<bool,
(vtkmstd::is_trivially_copyable<T0>::value &&
vtkmstd::is_trivially_copyable<T1>::value)>
{
};
template <typename T0, typename T1, typename T2>
struct AllTriviallyCopyable<T0, T1, T2>
: std::integral_constant<bool,
(vtkmstd::is_trivially_copyable<T0>::value &&
vtkmstd::is_trivially_copyable<T1>::value &&
vtkmstd::is_trivially_copyable<T2>::value)>
{
};
template <typename T0, typename T1, typename T2, typename T3>
struct AllTriviallyCopyable<T0, T1, T2, T3>
: std::integral_constant<
bool,
(vtkmstd::is_trivially_copyable<T0>::value && vtkmstd::is_trivially_copyable<T1>::value &&
vtkmstd::is_trivially_copyable<T2>::value && vtkmstd::is_trivially_copyable<T3>::value)>
{
};
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename... Ts>
struct AllTriviallyCopyable<T0, T1, T2, T3, T4, Ts...>
: std::integral_constant<
bool,
(vtkmstd::is_trivially_copyable<T0>::value && vtkmstd::is_trivially_copyable<T1>::value &&
vtkmstd::is_trivially_copyable<T2>::value && vtkmstd::is_trivially_copyable<T3>::value &&
vtkmstd::is_trivially_copyable<T4>::value && AllTriviallyCopyable<Ts...>::value)>
{
};
template <typename VariantType>
struct VariantTriviallyCopyable;
......@@ -127,59 +131,6 @@ struct VariantTriviallyCopyable<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>>
{
};
template <typename... Ts>
struct AllTriviallyConstructible;
template <>
struct AllTriviallyConstructible<> : std::true_type
{
};
template <typename T0>
struct AllTriviallyConstructible<T0>
: std::integral_constant<bool, (vtkmstd::is_trivially_constructible<T0>::value)>
{
};
template <typename T0, typename T1>
struct AllTriviallyConstructible<T0, T1>
: std::integral_constant<bool,
(vtkmstd::is_trivially_constructible<T0>::value &&
vtkmstd::is_trivially_constructible<T1>::value)>
{
};
template <typename T0, typename T1, typename T2>
struct AllTriviallyConstructible<T0, T1, T2>
: std::integral_constant<bool,
(vtkmstd::is_trivially_constructible<T0>::value &&
vtkmstd::is_trivially_constructible<T1>::value &&
vtkmstd::is_trivially_constructible<T2>::value)>
{
};
template <typename T0, typename T1, typename T2, typename T3>
struct AllTriviallyConstructible<T0, T1, T2, T3>
: std::integral_constant<bool,
(vtkmstd::is_trivially_constructible<T0>::value &&
vtkmstd::is_trivially_constructible<T1>::value &&
vtkmstd::is_trivially_constructible<T2>::value &&
vtkmstd::is_trivially_constructible<T3>::value)>
{
};
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename... Ts>
struct AllTriviallyConstructible<T0, T1, T2, T3, T4, Ts...>
: std::integral_constant<bool,
(vtkmstd::is_trivially_constructible<T0>::value &&
vtkmstd::is_trivially_constructible<T1>::value &&
vtkmstd::is_trivially_constructible<T2>::value &&
vtkmstd::is_trivially_constructible<T3>::value &&
vtkmstd::is_trivially_constructible<T4>::value &&
AllTriviallyConstructible<Ts...>::value)>
{
};
template <typename VariantType>
struct VariantTriviallyConstructible;
......@@ -189,22 +140,24 @@ struct VariantTriviallyConstructible<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts
{
};
// --------------------------------------------------------------------------------
// Variant superclass that defines its storage
template <typename... Ts>
struct VariantStorageImpl
{
typename vtkmstd::aligned_union<0, Ts...>::type Storage;
VariantUnion<Ts...> Storage;
vtkm::IdComponent Index;
template <vtkm::IdComponent Index>
using TypeAt = typename vtkm::ListAt<vtkm::List<Ts...>, Index>;
VariantStorageImpl() = default;
VTK_M_DEVICE void* GetPointer() { return reinterpret_cast<void*>(&this->Storage); }
VTK_M_DEVICE const void* GetPointer() const
VTK_M_DEVICE VariantStorageImpl(vtkm::internal::NullType dummy)
: Storage({ dummy })
{
return reinterpret_cast<const void*>(&this->Storage);
}
template <vtkm::IdComponent Index>
using TypeAt = typename vtkm::ListAt<vtkm::List<Ts...>, Index>;
VTK_M_DEVICE vtkm::IdComponent GetIndex() const noexcept { return this->Index; }
VTK_M_DEVICE bool IsValid() const noexcept
{
......@@ -226,12 +179,8 @@ struct VariantStorageImpl
-> decltype(f(std::declval<const TypeAt<0>&>(), args...))
{
VTKM_ASSERT(this->IsValid());
return detail::VariantCastAndCallImpl<decltype(f(std::declval<const TypeAt<0>&>(), args...))>(
brigand::list<Ts...>{},
this->GetIndex(),
std::forward<Functor>(f),
this->GetPointer(),
std::forward<Args>(args)...);
return detail::VariantCastAndCallImpl(
this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
}
template <typename Functor, typename... Args>
......@@ -240,15 +189,14 @@ struct VariantStorageImpl
-> decltype(f(std::declval<TypeAt<0>&>(), args...))
{
VTKM_ASSERT(this->IsValid());
return detail::VariantCastAndCallImpl<decltype(f(std::declval<TypeAt<0>&>(), args...))>(
brigand::list<Ts...>{},
this->GetIndex(),
std::forward<Functor>(f),
this->GetPointer(),
std::forward<Args>(args)...);
return detail::VariantCastAndCallImpl(
this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
}
};
// --------------------------------------------------------------------------------
// Variant superclass that helps preserve trivially copyable and trivially constructable
// properties where possible.
template <typename VariantType,
typename TriviallyConstructible =
typename VariantTriviallyConstructible<VariantType>::type,
......@@ -277,7 +225,11 @@ struct VariantConstructorImpl<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>,
std::false_type,
std::true_type> : VariantStorageImpl<Ts...>
{
VTK_M_DEVICE VariantConstructorImpl() { this->Index = -1; }
VTK_M_DEVICE VariantConstructorImpl()
: VariantStorageImpl<Ts...>(vtkm::internal::NullType{})
{
this->Index = -1;
}
// Any trivially copyable class is trivially destructable.
~VariantConstructorImpl() = default;
......@@ -294,20 +246,32 @@ struct VariantConstructorImpl<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>,
construct_type,
std::false_type> : VariantStorageImpl<Ts...>
{
VTK_M_DEVICE VariantConstructorImpl() { this->Index = -1; }
VTK_M_DEVICE VariantConstructorImpl()
: VariantStorageImpl<Ts...>(vtkm::internal::NullType{})
{
this->Index = -1;
}
VTK_M_DEVICE ~VariantConstructorImpl() { this->Reset(); }
VTK_M_DEVICE VariantConstructorImpl(const VariantConstructorImpl& src) noexcept
: VariantStorageImpl<Ts...>(vtkm::internal::NullType{})
{
src.CastAndCall(VariantCopyFunctor{}, this->GetPointer());
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->GetPointer());
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;
}
};
......@@ -323,20 +287,6 @@ class Variant : detail::VariantConstructorImpl<Variant<Ts...>>
using CheckTypes = vtkm::List<detail::VariantCheckType<Ts>...>;
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.
///