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
|
|
|
|
2020-02-25 23:45:03 +00:00
|
|
|
#include <vtkmstd/aligned_union.h>
|
2020-09-22 22:00:26 +00:00
|
|
|
#include <vtkmstd/is_trivial.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
|
|
|
|
{
|
|
|
|
|
|
|
|
struct VariantCopyFunctor
|
|
|
|
{
|
|
|
|
template <typename T>
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE void operator()(const T& src, void* destPointer) const noexcept
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
new (destPointer) T(src);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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 AllTriviallyCopyable;
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct AllTriviallyCopyable<> : std::true_type
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T0>
|
|
|
|
struct AllTriviallyCopyable<T0>
|
2019-10-30 21:53:20 +00:00
|
|
|
: std::integral_constant<bool, (vtkmstd::is_trivially_copyable<T0>::value)>
|
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 T0, typename T1>
|
|
|
|
struct AllTriviallyCopyable<T0, T1>
|
|
|
|
: std::integral_constant<bool,
|
2019-10-30 21:53:20 +00:00
|
|
|
(vtkmstd::is_trivially_copyable<T0>::value &&
|
|
|
|
vtkmstd::is_trivially_copyable<T1>::value)>
|
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 T0, typename T1, typename T2>
|
|
|
|
struct AllTriviallyCopyable<T0, T1, T2>
|
|
|
|
: std::integral_constant<bool,
|
2019-10-30 21:53:20 +00:00
|
|
|
(vtkmstd::is_trivially_copyable<T0>::value &&
|
|
|
|
vtkmstd::is_trivially_copyable<T1>::value &&
|
|
|
|
vtkmstd::is_trivially_copyable<T2>::value)>
|
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 T0, typename T1, typename T2, typename T3>
|
|
|
|
struct AllTriviallyCopyable<T0, T1, T2, T3>
|
2020-08-17 14:18:24 +00:00
|
|
|
: 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)>
|
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 T0, typename T1, typename T2, typename T3, typename T4, typename... Ts>
|
|
|
|
struct AllTriviallyCopyable<T0, T1, T2, T3, T4, Ts...>
|
2020-08-17 14:18:24 +00:00
|
|
|
: 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)>
|
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...>>
|
|
|
|
: AllTriviallyCopyable<Ts...>
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
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
|
|
|
};
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2020-09-22 22:00:26 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
template <typename... Ts>
|
2020-10-06 21:57:04 +00:00
|
|
|
struct VariantTriviallyConstructible<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>>
|
2020-09-22 22:00:26 +00:00
|
|
|
: AllTriviallyConstructible<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
|
|
|
template <typename... Ts>
|
|
|
|
struct VariantStorageImpl
|
|
|
|
{
|
2019-07-29 18:57:21 +00:00
|
|
|
typename vtkmstd::aligned_union<0, Ts...>::type Storage;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
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
|
|
|
|
|
|
|
template <vtkm::IdComponent Index>
|
2019-12-05 02:17:19 +00:00
|
|
|
using TypeAt = typename vtkm::ListAt<vtkm::List<Ts...>, 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
|
|
|
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE void* GetPointer() { return reinterpret_cast<void*>(&this->Storage); }
|
|
|
|
VTK_M_DEVICE const void* GetPointer() const
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
return reinterpret_cast<const void*>(&this->Storage);
|
|
|
|
}
|
|
|
|
|
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());
|
|
|
|
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)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
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)...);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE VariantConstructorImpl() { 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
|
|
|
{
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE VariantConstructorImpl() { this->Index = -1; }
|
|
|
|
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
|
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
|
|
|
{
|
|
|
|
src.CastAndCall(VariantCopyFunctor{}, this->GetPointer());
|
|
|
|
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
|
|
|
{
|
|
|
|
this->Reset();
|
|
|
|
src.CastAndCall(detail::VariantCopyFunctor{}, this->GetPointer());
|
|
|
|
this->Index = src.Index;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
class Variant : detail::VariantConstructorImpl<Variant<Ts...>>
|
|
|
|
{
|
|
|
|
using Superclass = detail::VariantConstructorImpl<Variant<Ts...>>;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
/// Returns the index of the type of object this variant is storing. If no object is currently
|
2020-09-22 22:00:26 +00:00
|
|
|
/// stored (i.e. the `Variant` is invalid), an invalid is returned.
|
2019-07-14 23:38:30 +00:00
|
|
|
///
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE vtkm::IdComponent GetIndex() const noexcept { return this->Superclass::GetIndex(); }
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2020-09-22 22:00:26 +00:00
|
|
|
/// Returns true if this `Variant` is storing an object from one of the types in the template
|
2019-07-14 23:38:30 +00:00
|
|
|
/// list, false otherwise.
|
|
|
|
///
|
2020-09-22 22:00:26 +00:00
|
|
|
/// 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.
|
|
|
|
///
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE bool IsValid() const noexcept { return this->Superclass::IsValid(); }
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
/// 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>
|
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
|
|
|
using TypeAt = typename Superclass::template TypeAt<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) };
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
new (this->GetPointer()) T(src);
|
|
|
|
this->Index = index;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
|
|
|
constexpr vtkm::IdComponent index = IndexOf<T>::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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
T* value = new (this->GetPointer()) T{ args... };
|
|
|
|
this->Index = I;
|
|
|
|
return *value;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
T* value = new (this->GetPointer()) T(il, args...);
|
|
|
|
this->Index = I;
|
|
|
|
return *value;
|
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
return *reinterpret_cast<TypeAt<I>*>(this->GetPointer());
|
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());
|
|
|
|
return *reinterpret_cast<const TypeAt<I>*>(this->GetPointer());
|
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());
|
|
|
|
return *reinterpret_cast<T*>(this->GetPointer());
|
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
return *reinterpret_cast<const T*>(this->GetPointer());
|
|
|
|
}
|
|
|
|
//@}
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/// 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
|
|
|
{
|
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->Superclass::CastAndCall(std::forward<Functor>(f), 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...))
|
|
|
|
{
|
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->Superclass::CastAndCall(std::forward<Functor>(f), 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.
|
|
|
|
///
|
2020-10-06 21:57:04 +00:00
|
|
|
VTK_M_DEVICE void Reset() noexcept { this->Superclass::Reset(); }
|
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
|