2019-07-14 23:38:30 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
|
|
|
//
|
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//============================================================================
|
|
|
|
|
2020-10-06 21:57:04 +00:00
|
|
|
#if !defined(VTK_M_DEVICE) || !defined(VTK_M_NAMESPACE)
|
|
|
|
#error VariantImpl.h must be included from Variant.h
|
|
|
|
// Some defines to make my IDE happy.
|
|
|
|
#define VTK_M_DEVICE
|
|
|
|
#define VTK_M_NAMESPACE tmp
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <vtkm/internal/VariantImplDetail.h>
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2019-12-05 02:17:19 +00:00
|
|
|
#include <vtkm/Deprecated.h>
|
|
|
|
#include <vtkm/List.h>
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
#include <vtkm/internal/Assume.h>
|
2019-10-30 21:53:20 +00:00
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
2020-10-06 21:57:04 +00:00
|
|
|
namespace VTK_M_NAMESPACE
|
|
|
|
{
|
2019-07-14 23:38:30 +00:00
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
// Forward declaration
|
|
|
|
template <typename... Ts>
|
|
|
|
class Variant;
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// 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;
|
|
|
|
|
2021-03-24 20:41:31 +00:00
|
|
|
struct VariantCopyConstructFunctor
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
2021-03-17 20:38:33 +00:00
|
|
|
template <typename T, typename UnionType>
|
|
|
|
VTK_M_DEVICE void operator()(const T& src, UnionType& destUnion) const noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
2021-03-17 20:38:33 +00:00
|
|
|
constexpr vtkm::IdComponent Index = vtkm::ListIndexOf<VariantUnionToList<UnionType>, T>::value;
|
2021-03-24 20:41:31 +00:00
|
|
|
// If we are using this functor, we can assume the union does not hold a valid type.
|
2021-03-17 20:38:33 +00:00
|
|
|
new (&VariantUnionGet<Index>(destUnion)) T(src);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-24 20:41:31 +00:00
|
|
|
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 DoCopy(const T& src, T& dest, std::true_type) const noexcept
|
|
|
|
{
|
|
|
|
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.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
struct VariantDestroyFunctor
|
|
|
|
{
|
|
|
|
template <typename T>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE void operator()(T& src) const noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
src.~T();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-01 23:05:02 +00:00
|
|
|
template <typename T>
|
|
|
|
struct VariantCheckType
|
|
|
|
{
|
|
|
|
// We are currently not allowing reference types (e.g. FooType&) or pointer types (e.g. FooType*)
|
|
|
|
// in Variant objects. References and pointers can fail badly when things are passed around
|
|
|
|
// devices. If you get a compiler error here, consider removing the reference or using something
|
|
|
|
// like std::decay to remove qualifiers on the type. (We may decide to do that automatically in
|
|
|
|
// the future.)
|
|
|
|
VTKM_STATIC_ASSERT_MSG(!std::is_reference<T>::value,
|
|
|
|
"References are not allowed in VTK-m Variant.");
|
|
|
|
VTKM_STATIC_ASSERT_MSG(!std::is_pointer<T>::value, "Pointers are not allowed in VTK-m Variant.");
|
|
|
|
};
|
|
|
|
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
template <typename VariantType>
|
|
|
|
struct VariantTriviallyCopyable;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
template <typename... Ts>
|
2020-10-06 21:57:04 +00:00
|
|
|
struct VariantTriviallyCopyable<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>>
|
2021-03-23 19:34:39 +00:00
|
|
|
: AllTriviallyCopyable<Ts...>
|
2020-09-22 22:00:26 +00:00
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename VariantType>
|
|
|
|
struct VariantTriviallyConstructible;
|
|
|
|
|
|
|
|
template <typename... Ts>
|
2020-10-06 21:57:04 +00:00
|
|
|
struct VariantTriviallyConstructible<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>>
|
2021-03-23 19:34:39 +00:00
|
|
|
: AllTriviallyConstructible<Ts...>
|
2020-09-22 22:00:26 +00:00
|
|
|
{
|
|
|
|
};
|
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// Variant superclass that defines its storage
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
template <typename... Ts>
|
|
|
|
struct VariantStorageImpl
|
|
|
|
{
|
2021-03-17 20:38:33 +00:00
|
|
|
VariantUnion<Ts...> Storage;
|
2020-09-22 22:00:26 +00:00
|
|
|
vtkm::IdComponent Index;
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
VariantStorageImpl() = default;
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
VTK_M_DEVICE VariantStorageImpl(vtkm::internal::NullType dummy)
|
|
|
|
: Storage({ dummy })
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
template <vtkm::IdComponent Index>
|
|
|
|
using TypeAt = typename vtkm::ListAt<vtkm::List<Ts...>, Index>;
|
|
|
|
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE vtkm::IdComponent GetIndex() const noexcept { return this->Index; }
|
|
|
|
VTK_M_DEVICE bool IsValid() const noexcept
|
2020-09-22 22:00:26 +00:00
|
|
|
{
|
|
|
|
return (this->Index >= 0) && (this->Index < static_cast<vtkm::IdComponent>(sizeof...(Ts)));
|
|
|
|
}
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE void Reset() noexcept
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
{
|
|
|
|
if (this->IsValid())
|
|
|
|
{
|
|
|
|
this->CastAndCall(detail::VariantDestroyFunctor{});
|
|
|
|
this->Index = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Functor, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE auto CastAndCall(Functor&& f, Args&&... args) const
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
noexcept(noexcept(f(std::declval<const TypeAt<0>&>(), args...)))
|
|
|
|
-> decltype(f(std::declval<const TypeAt<0>&>(), args...))
|
|
|
|
{
|
|
|
|
VTKM_ASSERT(this->IsValid());
|
2021-03-17 20:38:33 +00:00
|
|
|
return detail::VariantCastAndCallImpl(vtkm::ListSize<vtkm::List<Ts...>>{},
|
|
|
|
this->GetIndex(),
|
|
|
|
std::forward<Functor>(f),
|
|
|
|
this->Storage,
|
|
|
|
std::forward<Args>(args)...);
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Functor, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE auto CastAndCall(Functor&& f, Args&&... args) noexcept(
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
noexcept(f(std::declval<const TypeAt<0>&>(), args...)))
|
|
|
|
-> decltype(f(std::declval<TypeAt<0>&>(), args...))
|
|
|
|
{
|
|
|
|
VTKM_ASSERT(this->IsValid());
|
2021-03-17 20:38:33 +00:00
|
|
|
return detail::VariantCastAndCallImpl(vtkm::ListSize<vtkm::List<Ts...>>{},
|
|
|
|
this->GetIndex(),
|
|
|
|
std::forward<Functor>(f),
|
|
|
|
this->Storage,
|
|
|
|
std::forward<Args>(args)...);
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// Variant superclass that helps preserve trivially copyable and trivially constructable
|
|
|
|
// properties where possible.
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
template <typename VariantType,
|
2020-09-22 22:00:26 +00:00
|
|
|
typename TriviallyConstructible =
|
|
|
|
typename VariantTriviallyConstructible<VariantType>::type,
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
typename TriviallyCopyable = typename VariantTriviallyCopyable<VariantType>::type>
|
|
|
|
struct VariantConstructorImpl;
|
|
|
|
|
2020-09-22 22:00:26 +00:00
|
|
|
// Can trivially construct, deconstruct, and copy all data. (Probably all trivial classes.)
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
template <typename... Ts>
|
2020-10-06 21:57:04 +00:00
|
|
|
struct VariantConstructorImpl<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>,
|
|
|
|
std::true_type,
|
|
|
|
std::true_type> : VariantStorageImpl<Ts...>
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
{
|
|
|
|
VariantConstructorImpl() = default;
|
|
|
|
~VariantConstructorImpl() = default;
|
|
|
|
|
|
|
|
VariantConstructorImpl(const VariantConstructorImpl&) = default;
|
|
|
|
VariantConstructorImpl(VariantConstructorImpl&&) = default;
|
|
|
|
VariantConstructorImpl& operator=(const VariantConstructorImpl&) = default;
|
|
|
|
VariantConstructorImpl& operator=(VariantConstructorImpl&&) = default;
|
|
|
|
};
|
|
|
|
|
2020-09-22 22:00:26 +00:00
|
|
|
// Can trivially copy, but cannot trivially construct. Common if a class is simple but
|
|
|
|
// initializes itself.
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
template <typename... Ts>
|
2020-10-06 21:57:04 +00:00
|
|
|
struct VariantConstructorImpl<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>,
|
|
|
|
std::false_type,
|
|
|
|
std::true_type> : VariantStorageImpl<Ts...>
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
{
|
2021-03-17 20:38:33 +00:00
|
|
|
VTK_M_DEVICE VariantConstructorImpl()
|
|
|
|
: VariantStorageImpl<Ts...>(vtkm::internal::NullType{})
|
|
|
|
{
|
|
|
|
this->Index = -1;
|
|
|
|
}
|
2020-09-22 22:00:26 +00:00
|
|
|
|
|
|
|
// Any trivially copyable class is trivially destructable.
|
|
|
|
~VariantConstructorImpl() = default;
|
|
|
|
|
|
|
|
VariantConstructorImpl(const VariantConstructorImpl&) = default;
|
|
|
|
VariantConstructorImpl(VariantConstructorImpl&&) = default;
|
|
|
|
VariantConstructorImpl& operator=(const VariantConstructorImpl&) = default;
|
|
|
|
VariantConstructorImpl& operator=(VariantConstructorImpl&&) = default;
|
|
|
|
};
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
|
2020-09-22 22:00:26 +00:00
|
|
|
// Cannot trivially copy. We assume we cannot trivially construct/destruct.
|
|
|
|
template <typename construct_type, typename... Ts>
|
2020-10-06 21:57:04 +00:00
|
|
|
struct VariantConstructorImpl<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>,
|
|
|
|
construct_type,
|
|
|
|
std::false_type> : VariantStorageImpl<Ts...>
|
2020-09-22 22:00:26 +00:00
|
|
|
{
|
2021-03-17 20:38:33 +00:00
|
|
|
VTK_M_DEVICE VariantConstructorImpl()
|
|
|
|
: VariantStorageImpl<Ts...>(vtkm::internal::NullType{})
|
|
|
|
{
|
|
|
|
this->Index = -1;
|
|
|
|
}
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE ~VariantConstructorImpl() { this->Reset(); }
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE VariantConstructorImpl(const VariantConstructorImpl& src) noexcept
|
2021-03-17 20:38:33 +00:00
|
|
|
: VariantStorageImpl<Ts...>(vtkm::internal::NullType{})
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
{
|
2021-03-24 20:41:31 +00:00
|
|
|
src.CastAndCall(VariantCopyConstructFunctor{}, this->Storage);
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
this->Index = src.Index;
|
|
|
|
}
|
|
|
|
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE VariantConstructorImpl& operator=(const VariantConstructorImpl& src) noexcept
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
{
|
2021-03-24 20:41:31 +00:00
|
|
|
if (this->GetIndex() == src.GetIndex())
|
|
|
|
{
|
|
|
|
src.CastAndCall(detail::VariantCopyFunctor{}, this->Storage);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->Reset();
|
|
|
|
src.CastAndCall(detail::VariantCopyConstructFunctor{}, this->Storage);
|
|
|
|
this->Index = src.Index;
|
|
|
|
}
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
class Variant : detail::VariantConstructorImpl<Variant<Ts...>>
|
|
|
|
{
|
|
|
|
using Superclass = detail::VariantConstructorImpl<Variant<Ts...>>;
|
2021-03-01 23:05:02 +00:00
|
|
|
|
|
|
|
// Type not used, but has the compiler check all the types for validity.
|
|
|
|
using CheckTypes = vtkm::List<detail::VariantCheckType<Ts>...>;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
/// 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 <typename T>
|
2020-01-09 15:19:47 +00:00
|
|
|
using IndexOf = vtkm::ListIndexOf<vtkm::List<Ts...>, T>;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
/// Returns the index for the given type (or -1 if that type is not in the list).
|
|
|
|
///
|
|
|
|
template <typename T>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE static constexpr vtkm::IdComponent GetIndexOf()
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
return IndexOf<T>::value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Type that converts to the type at the given index.
|
|
|
|
///
|
|
|
|
template <vtkm::IdComponent Index>
|
2021-03-17 20:38:33 +00:00
|
|
|
using TypeAt = typename vtkm::ListAt<vtkm::List<Ts...>, Index>;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
/// The number of types representable by this Variant.
|
|
|
|
///
|
|
|
|
static constexpr vtkm::IdComponent NumberOfTypes = vtkm::IdComponent{ sizeof...(Ts) };
|
|
|
|
|
2021-03-17 20:38:33 +00:00
|
|
|
/// 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);
|
|
|
|
}
|
|
|
|
|
2019-07-16 21:41:27 +00:00
|
|
|
Variant() = default;
|
Register Variant as trivially copyable if possible
The Variant template can hold any type. If it is holding a type that is
non-copyable, then it has to make sure that appropriate constructors,
copiers, movers, and destructors are called.
Previously, these were called even the Variant was holding a trivially
copyable class because no harm no foul. If you were holding a trivially
copyable class and did a memcpy, that work work, which should make it
possible to copy between host and device, right?
In theory yes, but in practice no. The problem is that Cuda is
outsmarting the code. It is checking that Variant is not trivially-
copyable by C++ semantics and refusing to push it.
So, change Variant to check to see if all its supported classes are
trivially copyable. If they are, then it use the default constructors,
destructors, movers, and copiers so that C++ recognizes it as trivially
copyable.
2019-10-26 03:43:22 +00:00
|
|
|
~Variant() = default;
|
|
|
|
Variant(const Variant&) = default;
|
|
|
|
Variant(Variant&&) = default;
|
|
|
|
Variant& operator=(const Variant&) = default;
|
|
|
|
Variant& operator=(Variant&&) = default;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
template <typename T>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE Variant(const T& src) noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
2019-07-15 04:51:28 +00:00
|
|
|
constexpr vtkm::IdComponent index = GetIndexOf<T>();
|
2019-07-14 23:38:30 +00:00
|
|
|
// 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");
|
|
|
|
|
|
|
|
this->Index = index;
|
2021-03-17 20:38:33 +00:00
|
|
|
new (&this->Get<index>()) T(src);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2021-03-17 20:38:33 +00:00
|
|
|
VTK_M_DEVICE Variant& operator=(const T& src)
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
2021-03-24 20:41:31 +00:00
|
|
|
if (this->GetIndex() == this->GetIndexOf<T>())
|
|
|
|
{
|
|
|
|
this->Get<T>() = src;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->Emplace<T>(src);
|
|
|
|
}
|
2021-03-17 20:38:33 +00:00
|
|
|
return *this;
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE T& Emplace(Args&&... args)
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
constexpr vtkm::IdComponent I = GetIndexOf<T>();
|
|
|
|
VTKM_STATIC_ASSERT_MSG(I >= 0, "Variant::Emplace called with invalid type.");
|
|
|
|
return this->EmplaceImpl<T, I>(std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, typename U, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE T& Emplace(std::initializer_list<U> il, Args&&... args)
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
constexpr vtkm::IdComponent I = GetIndexOf<T>();
|
|
|
|
VTKM_STATIC_ASSERT_MSG(I >= 0, "Variant::Emplace called with invalid type.");
|
|
|
|
return this->EmplaceImpl<T, I>(il, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <vtkm::IdComponent I, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE TypeAt<I>& Emplace(Args&&... args)
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
VTKM_STATIC_ASSERT_MSG((I >= 0) && (I < NumberOfTypes),
|
|
|
|
"Variant::Emplace called with invalid index");
|
|
|
|
return this->EmplaceImpl<TypeAt<I>, I>(std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <vtkm::IdComponent I, typename U, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE TypeAt<I>& Emplace(std::initializer_list<U> il, Args&&... args)
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
VTKM_STATIC_ASSERT_MSG((I >= 0) && (I < NumberOfTypes),
|
|
|
|
"Variant::Emplace called with invalid index");
|
|
|
|
return this->EmplaceImpl<TypeAt<I>, I>(il, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
template <typename T, vtkm::IdComponent I, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE T& EmplaceImpl(Args&&... args)
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
this->Reset();
|
|
|
|
this->Index = I;
|
2021-03-17 20:38:33 +00:00
|
|
|
return *(new (&this->Get<I>()) T{ args... });
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, vtkm::IdComponent I, typename U, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE T& EmplaceImpl(std::initializer_list<U> il, Args&&... args)
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
this->Reset();
|
|
|
|
this->Index = I;
|
2021-03-17 20:38:33 +00:00
|
|
|
return *(new (&this->Get<I>()) T(il, args...));
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
//@{
|
|
|
|
/// Returns the value as the type at the given index. The behavior is undefined if the
|
|
|
|
/// variant does not contain the value at the given index.
|
|
|
|
///
|
2019-07-16 21:41:27 +00:00
|
|
|
template <vtkm::IdComponent I>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE TypeAt<I>& Get() noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
2019-07-16 21:41:27 +00:00
|
|
|
VTKM_ASSERT(I == this->GetIndex());
|
2021-03-17 20:38:33 +00:00
|
|
|
return detail::VariantUnionGet<I>(this->Storage);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
2019-07-16 21:41:27 +00:00
|
|
|
template <vtkm::IdComponent I>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE const TypeAt<I>& Get() const noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
2019-07-16 21:41:27 +00:00
|
|
|
VTKM_ASSERT(I == this->GetIndex());
|
2021-03-17 20:38:33 +00:00
|
|
|
return detail::VariantUnionGet<I>(this->Storage);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
//@}
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/// Returns the value as the given type. The behavior is undefined if the variant does not
|
|
|
|
/// contain a value of the given type.
|
|
|
|
///
|
|
|
|
template <typename T>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE T& Get() noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
VTKM_ASSERT(this->GetIndexOf<T>() == this->GetIndex());
|
2021-03-17 20:38:33 +00:00
|
|
|
return detail::VariantUnionGet<IndexOf<T>::value>(this->Storage);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE const T& Get() const noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
VTKM_ASSERT(this->GetIndexOf<T>() == this->GetIndex());
|
2021-03-17 20:38:33 +00:00
|
|
|
return detail::VariantUnionGet<IndexOf<T>::value>(this->Storage);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
//@}
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/// Given a functor object, calls the functor with the contained object cast to the appropriate
|
|
|
|
/// type. If extra \c args are given, then those are also passed to the functor after the cast
|
|
|
|
/// object. If the functor returns a value, that value is returned from \c CastAndCall.
|
|
|
|
///
|
|
|
|
/// The results are undefined if the Variant is not valid.
|
|
|
|
///
|
|
|
|
template <typename Functor, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE auto CastAndCall(Functor&& f, Args&&... args) const
|
2019-07-25 21:25:29 +00:00
|
|
|
noexcept(noexcept(f(std::declval<const TypeAt<0>&>(), args...)))
|
|
|
|
-> decltype(f(std::declval<const TypeAt<0>&>(), args...))
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_ASSERT(this->IsValid());
|
|
|
|
return detail::VariantCastAndCallImpl(
|
|
|
|
std::integral_constant<vtkm::IdComponent, NumberOfTypes>{},
|
|
|
|
this->GetIndex(),
|
|
|
|
std::forward<Functor>(f),
|
|
|
|
this->Storage,
|
|
|
|
std::forward<Args>(args)...);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Functor, typename... Args>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE auto CastAndCall(Functor&& f, Args&&... args) noexcept(
|
2019-07-25 21:25:29 +00:00
|
|
|
noexcept(f(std::declval<const TypeAt<0>&>(), args...)))
|
2019-07-14 23:38:30 +00:00
|
|
|
-> decltype(f(std::declval<TypeAt<0>&>(), args...))
|
|
|
|
{
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_ASSERT(this->IsValid());
|
|
|
|
return detail::VariantCastAndCallImpl(
|
|
|
|
std::integral_constant<vtkm::IdComponent, NumberOfTypes>{},
|
|
|
|
this->GetIndex(),
|
|
|
|
std::forward<Functor>(f),
|
|
|
|
this->Storage,
|
|
|
|
std::forward<Args>(args)...);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Destroys any object the Variant is holding and sets the Variant to an invalid state. This
|
|
|
|
/// method is not thread safe.
|
|
|
|
///
|
2021-03-17 20:38:33 +00:00
|
|
|
VTK_M_DEVICE void Reset() noexcept
|
|
|
|
{
|
|
|
|
if (this->IsValid())
|
|
|
|
{
|
|
|
|
this->CastAndCall(detail::VariantDestroyFunctor{});
|
|
|
|
this->Index = -1;
|
|
|
|
}
|
|
|
|
}
|
2019-07-14 23:38:30 +00:00
|
|
|
};
|
2019-07-15 03:35:45 +00:00
|
|
|
|
|
|
|
/// \brief Convert a ListTag to a Variant.
|
|
|
|
///
|
2019-12-05 02:17:19 +00:00
|
|
|
/// Depricated. Use ListAsVariant instead.
|
|
|
|
///
|
2019-07-15 03:35:45 +00:00
|
|
|
template <typename ListTag>
|
2019-12-05 02:17:19 +00:00
|
|
|
using ListTagAsVariant VTKM_DEPRECATED(
|
|
|
|
1.6,
|
|
|
|
"vtkm::ListTag is no longer supported. Use vtkm::List instead.") =
|
2020-10-06 21:57:04 +00:00
|
|
|
vtkm::ListApply<ListTag, vtkm::VTK_M_NAMESPACE::internal::Variant>;
|
2019-12-05 02:17:19 +00:00
|
|
|
|
|
|
|
/// \brief Convert a `List` to a `Variant`.
|
|
|
|
///
|
|
|
|
template <typename List>
|
2020-10-06 21:57:04 +00:00
|
|
|
using ListAsVariant = vtkm::ListApply<List, vtkm::VTK_M_NAMESPACE::internal::Variant>;
|
|
|
|
}
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
2020-10-06 21:57:04 +00:00
|
|
|
} // namespace vtkm::VTK_M_NAMESPACE::internal
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2020-10-06 21:57:04 +00:00
|
|
|
#undef VTK_M_DEVICE
|
|
|
|
#undef VTK_M_NAMESPACE
|