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.
|
|
|
|
//============================================================================
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
#include <vtkm/exec/Variant.h>
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
#include <vtkm/testing/Testing.h>
|
|
|
|
|
2020-10-08 18:02:27 +00:00
|
|
|
#include <cstdlib>
|
2019-07-14 23:38:30 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2019-10-27 13:33:45 +00:00
|
|
|
namespace test_variant
|
2019-07-14 23:38:30 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
template <vtkm::IdComponent Index>
|
|
|
|
struct TypePlaceholder
|
|
|
|
{
|
2022-07-25 16:07:22 +00:00
|
|
|
vtkm::IdComponent Value = Index;
|
2019-07-14 23:38:30 +00:00
|
|
|
};
|
|
|
|
|
2020-09-22 22:00:26 +00:00
|
|
|
// A class that is trivially copiable but not totally trivial.
|
|
|
|
struct TrivialCopy
|
|
|
|
{
|
|
|
|
vtkm::Id Value = 0;
|
|
|
|
};
|
|
|
|
|
2020-10-08 18:02:27 +00:00
|
|
|
static vtkm::Id g_NonTrivialCount;
|
|
|
|
|
|
|
|
// A class that must is not trivial to copy nor construct.
|
|
|
|
struct NonTrivial
|
|
|
|
{
|
2021-03-24 20:41:31 +00:00
|
|
|
vtkm::Id Value;
|
2020-10-08 18:02:27 +00:00
|
|
|
NonTrivial* Self;
|
|
|
|
|
|
|
|
void CheckState() const
|
|
|
|
{
|
|
|
|
VTKM_TEST_ASSERT(this->Value == 12345);
|
|
|
|
VTKM_TEST_ASSERT(this->Self == this);
|
|
|
|
}
|
|
|
|
|
|
|
|
NonTrivial()
|
2021-03-24 20:41:31 +00:00
|
|
|
: Value(12345)
|
|
|
|
, Self(this)
|
2020-10-08 18:02:27 +00:00
|
|
|
{
|
|
|
|
this->CheckState();
|
|
|
|
++g_NonTrivialCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
NonTrivial(const NonTrivial& src)
|
2021-03-24 20:41:31 +00:00
|
|
|
: Value(src.Value)
|
2020-10-08 18:02:27 +00:00
|
|
|
{
|
|
|
|
src.CheckState();
|
2021-03-24 20:41:31 +00:00
|
|
|
this->Self = this;
|
|
|
|
this->CheckState();
|
2020-10-08 18:02:27 +00:00
|
|
|
++g_NonTrivialCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
NonTrivial& operator=(const NonTrivial& src)
|
|
|
|
{
|
|
|
|
this->CheckState();
|
|
|
|
src.CheckState();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~NonTrivial()
|
|
|
|
{
|
|
|
|
if ((this->Value == 12345) && (this->Self == this))
|
|
|
|
{
|
|
|
|
// Normal destruction
|
|
|
|
this->Value = -1;
|
|
|
|
this->Self = nullptr;
|
|
|
|
--g_NonTrivialCount;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Normally we would use VTKM_TEST_ASSERT or VTKM_TEST_FAIL, but it's not good to throw
|
|
|
|
// exceptions from destructors (especially since Variant marks these calls as noexcept).
|
|
|
|
// Instead, just check and terminate the program.
|
|
|
|
std::cout << "ERROR at " << __FILE__ << ":" << __LINE__ << ":\n";
|
|
|
|
std::cout << "Destroying a class that was not properly constructed." << std::endl;
|
|
|
|
std::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
void TestSize()
|
|
|
|
{
|
|
|
|
std::cout << "Test size" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<float, double, char, short, int, long>;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
constexpr size_t variantSize = sizeof(VariantType);
|
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(variantSize <= 16,
|
|
|
|
"Size of variant should not be larger than biggest type plus and index. ",
|
|
|
|
variantSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestIndexing()
|
|
|
|
{
|
|
|
|
std::cout << "Test indexing" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<TypePlaceholder<0>,
|
|
|
|
TypePlaceholder<1>,
|
|
|
|
TypePlaceholder<2>,
|
|
|
|
TypePlaceholder<3>,
|
|
|
|
TypePlaceholder<4>,
|
|
|
|
TypePlaceholder<5>,
|
|
|
|
TypePlaceholder<6>,
|
|
|
|
TypePlaceholder<7>,
|
|
|
|
TypePlaceholder<8>,
|
|
|
|
TypePlaceholder<9>,
|
|
|
|
TypePlaceholder<10>,
|
|
|
|
TypePlaceholder<11>,
|
|
|
|
TypePlaceholder<12>,
|
|
|
|
TypePlaceholder<13>,
|
|
|
|
TypePlaceholder<14>,
|
|
|
|
TypePlaceholder<15>,
|
|
|
|
TypePlaceholder<16>,
|
|
|
|
TypePlaceholder<17>,
|
|
|
|
TypePlaceholder<18>,
|
|
|
|
TypePlaceholder<19>,
|
|
|
|
TypePlaceholder<20>,
|
|
|
|
TypePlaceholder<21>,
|
|
|
|
TypePlaceholder<22>,
|
|
|
|
TypePlaceholder<23>,
|
|
|
|
TypePlaceholder<24>,
|
|
|
|
TypePlaceholder<25>,
|
|
|
|
TypePlaceholder<26>,
|
|
|
|
TypePlaceholder<27>,
|
|
|
|
TypePlaceholder<28>,
|
|
|
|
TypePlaceholder<29>>;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
VariantType variant;
|
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<0>>::value == 0);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<1>>::value == 1);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<2>>::value == 2);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<3>>::value == 3);
|
2020-01-09 15:19:47 +00:00
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<4>>::value == 4);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<5>>::value == 5);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<6>>::value == 6);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<7>>::value == 7);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<8>>::value == 8);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<9>>::value == 9);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<10>>::value == 10);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<11>>::value == 11);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<12>>::value == 12);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<13>>::value == 13);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<14>>::value == 14);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<15>>::value == 15);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<16>>::value == 16);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<17>>::value == 17);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<18>>::value == 18);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<19>>::value == 19);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<20>>::value == 20);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<21>>::value == 21);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<22>>::value == 22);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<23>>::value == 23);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<24>>::value == 24);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<25>>::value == 25);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<26>>::value == 26);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<27>>::value == 27);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<28>>::value == 28);
|
|
|
|
VTKM_TEST_ASSERT(VariantType::IndexOf<TypePlaceholder<29>>::value == 29);
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<0>>() == 0);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<1>>() == 1);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<2>>() == 2);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<3>>() == 3);
|
2020-01-09 15:19:47 +00:00
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<4>>() == 4);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<5>>() == 5);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<6>>() == 6);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<7>>() == 7);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<8>>() == 8);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<9>>() == 9);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<10>>() == 10);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<11>>() == 11);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<12>>() == 12);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<13>>() == 13);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<14>>() == 14);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<15>>() == 15);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<16>>() == 16);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<17>>() == 17);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<18>>() == 18);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<19>>() == 19);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<20>>() == 20);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<21>>() == 21);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<22>>() == 22);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<23>>() == 23);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<24>>() == 24);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<25>>() == 25);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<26>>() == 26);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<27>>() == 27);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<28>>() == 28);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndexOf<TypePlaceholder<29>>() == 29);
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<0>, TypePlaceholder<0>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<1>, TypePlaceholder<1>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<2>, TypePlaceholder<2>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<3>, TypePlaceholder<3>>::value));
|
2020-01-09 15:19:47 +00:00
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<4>, TypePlaceholder<4>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<5>, TypePlaceholder<5>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<6>, TypePlaceholder<6>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<7>, TypePlaceholder<7>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<8>, TypePlaceholder<8>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<9>, TypePlaceholder<9>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<10>, TypePlaceholder<10>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<11>, TypePlaceholder<11>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<12>, TypePlaceholder<12>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<13>, TypePlaceholder<13>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<14>, TypePlaceholder<14>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<15>, TypePlaceholder<15>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<16>, TypePlaceholder<16>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<17>, TypePlaceholder<17>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<18>, TypePlaceholder<18>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<19>, TypePlaceholder<19>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<20>, TypePlaceholder<20>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<21>, TypePlaceholder<21>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<22>, TypePlaceholder<22>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<23>, TypePlaceholder<23>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<24>, TypePlaceholder<24>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<25>, TypePlaceholder<25>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<26>, TypePlaceholder<26>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<27>, TypePlaceholder<27>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<28>, TypePlaceholder<28>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((std::is_same<VariantType::TypeAt<29>, TypePlaceholder<29>>::value));
|
2021-10-04 16:19:25 +00:00
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(VariantType::CanStore<TypePlaceholder<2>>::value);
|
|
|
|
VTKM_TEST_ASSERT(!VariantType::CanStore<TypePlaceholder<100>>::value);
|
|
|
|
VTKM_TEST_ASSERT(variant.GetCanStore<TypePlaceholder<3>>());
|
|
|
|
VTKM_TEST_ASSERT(!variant.GetCanStore<TypePlaceholder<101>>());
|
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
|
|
|
void TestTriviallyCopyable()
|
|
|
|
{
|
2021-03-01 22:10:10 +00:00
|
|
|
#ifdef VTKM_USE_STD_IS_TRIVIAL
|
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
|
|
|
// Make sure base types are behaving as expected
|
2021-04-01 20:47:51 +00:00
|
|
|
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_constructible<float>::value);
|
|
|
|
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable<float>::value);
|
|
|
|
VTKM_STATIC_ASSERT(vtkmstd::is_trivial<float>::value);
|
|
|
|
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_constructible<int>::value);
|
|
|
|
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable<int>::value);
|
|
|
|
VTKM_STATIC_ASSERT(vtkmstd::is_trivial<int>::value);
|
|
|
|
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_constructible<NonTrivial>::value);
|
|
|
|
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_copyable<NonTrivial>::value);
|
|
|
|
VTKM_STATIC_ASSERT(!vtkmstd::is_trivial<NonTrivial>::value);
|
|
|
|
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_constructible<TrivialCopy>::value);
|
|
|
|
VTKM_STATIC_ASSERT(vtkmstd::is_trivially_copyable<TrivialCopy>::value);
|
|
|
|
VTKM_STATIC_ASSERT(!vtkmstd::is_trivial<TrivialCopy>::value);
|
2020-09-22 22:00:26 +00:00
|
|
|
|
|
|
|
// A variant of trivially constructable things should be trivially constructable
|
2020-10-06 21:57:04 +00:00
|
|
|
VTKM_STATIC_ASSERT(
|
2022-11-01 13:52:41 +00:00
|
|
|
(vtkmstd::is_trivially_constructible<vtkm::exec::detail::VariantUnion<float, int>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((vtkmstd::is_trivially_constructible<vtkm::exec::Variant<float, int>>::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
|
|
|
|
|
|
|
// A variant of trivially copyable things should be trivially copyable
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_STATIC_ASSERT((vtkmstd::is_trivially_copyable<
|
2022-11-01 13:52:41 +00:00
|
|
|
vtkm::exec::detail::VariantUnion<float, int, TrivialCopy>>::value));
|
|
|
|
VTKM_STATIC_ASSERT(
|
|
|
|
(vtkmstd::is_trivially_copyable<vtkm::exec::Variant<float, int, TrivialCopy>>::value));
|
2020-09-22 22:00:26 +00:00
|
|
|
|
|
|
|
// A variant of any non-trivially constructable things is not trivially copyable
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
|
2022-11-01 13:52:41 +00:00
|
|
|
vtkm::exec::detail::VariantUnion<NonTrivial, float, int>>::value));
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
|
2022-11-01 13:52:41 +00:00
|
|
|
vtkm::exec::detail::VariantUnion<float, NonTrivial, int>>::value));
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_constructible<
|
2022-11-01 13:52:41 +00:00
|
|
|
vtkm::exec::detail::VariantUnion<float, int, NonTrivial>>::value));
|
|
|
|
VTKM_STATIC_ASSERT(
|
|
|
|
(!vtkmstd::is_trivially_constructible<vtkm::exec::Variant<NonTrivial, float, int>>::value));
|
|
|
|
VTKM_STATIC_ASSERT(
|
|
|
|
(!vtkmstd::is_trivially_constructible<vtkm::exec::Variant<float, NonTrivial, int>>::value));
|
|
|
|
VTKM_STATIC_ASSERT(
|
|
|
|
(!vtkmstd::is_trivially_constructible<vtkm::exec::Variant<float, int, NonTrivial>>::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
|
|
|
|
|
|
|
// A variant of any non-trivially copyable things is not trivially copyable
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable<
|
2022-11-01 13:52:41 +00:00
|
|
|
vtkm::exec::detail::VariantUnion<NonTrivial, float, int>>::value));
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable<
|
2022-11-01 13:52:41 +00:00
|
|
|
vtkm::exec::detail::VariantUnion<float, NonTrivial, int>>::value));
|
2021-03-17 20:38:33 +00:00
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivially_copyable<
|
2022-11-01 13:52:41 +00:00
|
|
|
vtkm::exec::detail::VariantUnion<float, int, NonTrivial>>::value));
|
2020-10-06 21:57:04 +00:00
|
|
|
VTKM_STATIC_ASSERT(
|
2022-11-01 13:52:41 +00:00
|
|
|
(!vtkmstd::is_trivially_copyable<vtkm::exec::Variant<NonTrivial, float, int>>::value));
|
2020-09-22 22:00:26 +00:00
|
|
|
VTKM_STATIC_ASSERT(
|
2022-11-01 13:52:41 +00:00
|
|
|
(!vtkmstd::is_trivially_copyable<vtkm::exec::Variant<float, NonTrivial, int>>::value));
|
|
|
|
VTKM_STATIC_ASSERT(
|
|
|
|
(!vtkmstd::is_trivially_copyable<vtkm::exec::Variant<float, int, NonTrivial>>::value));
|
|
|
|
|
|
|
|
// A variant of trivial things should be trivial
|
|
|
|
VTKM_STATIC_ASSERT((vtkmstd::is_trivial<vtkm::exec::Variant<float, int>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivial<vtkm::exec::Variant<float, int, TrivialCopy>>::value));
|
|
|
|
VTKM_STATIC_ASSERT((!vtkmstd::is_trivial<vtkm::exec::Variant<float, int, NonTrivial>>::value));
|
2021-04-01 20:47:51 +00:00
|
|
|
#endif // VTKM_USE_STD_IS_TRIVIAL
|
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
|
|
|
struct TestFunctor
|
|
|
|
{
|
|
|
|
template <vtkm::IdComponent Index>
|
|
|
|
vtkm::FloatDefault operator()(TypePlaceholder<Index>, vtkm::Id expectedValue)
|
|
|
|
{
|
|
|
|
VTKM_TEST_ASSERT(Index == expectedValue, "Index = ", Index, ", expected = ", expectedValue);
|
|
|
|
return TestValue(expectedValue, vtkm::FloatDefault{});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-07-25 16:07:22 +00:00
|
|
|
struct TestFunctorModify
|
|
|
|
{
|
|
|
|
template <vtkm::IdComponent Index>
|
|
|
|
void operator()(TypePlaceholder<Index>& object, vtkm::Id expectedValue)
|
|
|
|
{
|
|
|
|
VTKM_TEST_ASSERT(Index == expectedValue, "Index = ", Index, ", expected = ", expectedValue);
|
|
|
|
VTKM_TEST_ASSERT(object.Value == expectedValue);
|
|
|
|
++object.Value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
void TestGet()
|
|
|
|
{
|
|
|
|
std::cout << "Test Get" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<TypePlaceholder<0>,
|
|
|
|
TypePlaceholder<1>,
|
|
|
|
vtkm::Id,
|
|
|
|
TypePlaceholder<3>,
|
|
|
|
TypePlaceholder<4>,
|
|
|
|
TypePlaceholder<5>,
|
|
|
|
TypePlaceholder<6>,
|
|
|
|
TypePlaceholder<7>,
|
|
|
|
TypePlaceholder<8>,
|
|
|
|
TypePlaceholder<9>,
|
|
|
|
TypePlaceholder<10>,
|
|
|
|
TypePlaceholder<11>,
|
|
|
|
TypePlaceholder<12>,
|
|
|
|
TypePlaceholder<13>,
|
|
|
|
TypePlaceholder<14>,
|
|
|
|
TypePlaceholder<15>,
|
|
|
|
TypePlaceholder<16>,
|
|
|
|
TypePlaceholder<17>,
|
|
|
|
TypePlaceholder<18>,
|
|
|
|
TypePlaceholder<19>,
|
|
|
|
TypePlaceholder<20>,
|
|
|
|
TypePlaceholder<21>,
|
|
|
|
TypePlaceholder<22>,
|
|
|
|
TypePlaceholder<23>,
|
|
|
|
TypePlaceholder<24>,
|
|
|
|
TypePlaceholder<25>,
|
|
|
|
TypePlaceholder<26>,
|
|
|
|
vtkm::Float32,
|
|
|
|
TypePlaceholder<28>,
|
|
|
|
TypePlaceholder<29>>;
|
2020-01-09 15:19:47 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
const vtkm::Id expectedValue = TestValue(3, vtkm::Id{});
|
|
|
|
|
|
|
|
VariantType variant = expectedValue;
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndex() == 2);
|
2022-08-05 18:35:57 +00:00
|
|
|
VTKM_TEST_ASSERT(variant.IsType<vtkm::Id>());
|
|
|
|
VTKM_TEST_ASSERT(!variant.IsType<vtkm::Float32>());
|
2020-01-09 15:19:47 +00:00
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(variant.Get<2>() == expectedValue);
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2020-01-09 15:19:47 +00:00
|
|
|
VTKM_TEST_ASSERT(variant.Get<vtkm::Id>() == expectedValue);
|
2021-10-04 16:19:25 +00:00
|
|
|
|
|
|
|
// This line should compile, but will assert if you actually try to run it.
|
|
|
|
//variant.Get<TypePlaceholder<100>>();
|
2020-01-09 15:19:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
const vtkm::Float32 expectedValue = TestValue(4, vtkm::Float32{});
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2020-01-09 15:19:47 +00:00
|
|
|
VariantType variant = expectedValue;
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndex() == 27);
|
2019-07-14 23:38:30 +00:00
|
|
|
|
2020-01-09 15:19:47 +00:00
|
|
|
VTKM_TEST_ASSERT(variant.Get<27>() == expectedValue);
|
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(variant.Get<vtkm::Float32>() == expectedValue);
|
|
|
|
}
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestCastAndCall()
|
|
|
|
{
|
|
|
|
std::cout << "Test CastAndCall" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<TypePlaceholder<0>,
|
|
|
|
TypePlaceholder<1>,
|
|
|
|
TypePlaceholder<2>,
|
|
|
|
TypePlaceholder<3>,
|
|
|
|
TypePlaceholder<4>,
|
|
|
|
TypePlaceholder<5>,
|
|
|
|
TypePlaceholder<6>,
|
|
|
|
TypePlaceholder<7>,
|
|
|
|
TypePlaceholder<8>,
|
|
|
|
TypePlaceholder<9>,
|
|
|
|
TypePlaceholder<10>,
|
|
|
|
TypePlaceholder<11>,
|
|
|
|
TypePlaceholder<12>,
|
|
|
|
TypePlaceholder<13>,
|
|
|
|
TypePlaceholder<14>,
|
|
|
|
TypePlaceholder<15>,
|
|
|
|
TypePlaceholder<16>,
|
|
|
|
TypePlaceholder<17>,
|
|
|
|
TypePlaceholder<18>,
|
|
|
|
TypePlaceholder<19>,
|
|
|
|
TypePlaceholder<20>,
|
|
|
|
TypePlaceholder<21>,
|
|
|
|
TypePlaceholder<22>,
|
|
|
|
TypePlaceholder<23>,
|
|
|
|
TypePlaceholder<24>,
|
|
|
|
TypePlaceholder<25>,
|
|
|
|
TypePlaceholder<26>,
|
|
|
|
TypePlaceholder<27>,
|
|
|
|
TypePlaceholder<28>,
|
|
|
|
TypePlaceholder<29>>;
|
2019-07-14 23:38:30 +00:00
|
|
|
vtkm::FloatDefault result;
|
|
|
|
|
|
|
|
VariantType variant0{ TypePlaceholder<0>{} };
|
|
|
|
result = variant0.CastAndCall(TestFunctor(), 0);
|
|
|
|
VTKM_TEST_ASSERT(test_equal(result, TestValue(0, vtkm::FloatDefault{})));
|
|
|
|
|
|
|
|
VariantType variant1{ TypePlaceholder<1>{} };
|
|
|
|
result = variant1.CastAndCall(TestFunctor(), 1);
|
|
|
|
VTKM_TEST_ASSERT(test_equal(result, TestValue(1, vtkm::FloatDefault{})));
|
|
|
|
|
|
|
|
const VariantType variant2{ TypePlaceholder<2>{} };
|
|
|
|
result = variant2.CastAndCall(TestFunctor(), 2);
|
|
|
|
VTKM_TEST_ASSERT(test_equal(result, TestValue(2, vtkm::FloatDefault{})));
|
|
|
|
|
|
|
|
VariantType variant3{ TypePlaceholder<3>{} };
|
|
|
|
result = variant3.CastAndCall(TestFunctor(), 3);
|
|
|
|
VTKM_TEST_ASSERT(test_equal(result, TestValue(3, vtkm::FloatDefault{})));
|
2020-01-09 15:19:47 +00:00
|
|
|
|
|
|
|
VariantType variant26{ TypePlaceholder<26>{} };
|
|
|
|
result = variant26.CastAndCall(TestFunctor(), 26);
|
|
|
|
VTKM_TEST_ASSERT(test_equal(result, TestValue(26, vtkm::FloatDefault{})));
|
2022-07-25 16:07:22 +00:00
|
|
|
|
|
|
|
variant1.CastAndCall(TestFunctorModify{}, 1);
|
|
|
|
VTKM_TEST_ASSERT(variant1.Get<1>().Value == 2, "Variant object not updated.");
|
Fix Variant::CastAndCall SFINAE for auto return type functors
`Variant::CastAndCall` was using the C++11 style for an `auto` return
where the return type was specified with a `->` that got the `decltype`
of the return value of the functor. This was used as part of SFINAE to
pick whether you needed the const or non-const version.
However, this was causing a problem with functions that got an error
when deducing the return type for that. This was particularly
problematic for lambda functions. For example, say you have the
following simple `CastAndCall`.
```cpp
variant.CastAndCall([](auto& x){ ++x; });
```
To determine the return type of the lambda (`void`), the function has to
be compiled. But when it is compiled with a const type, which happens
when deducing the const version of `CastAndCall`, you get a compile
error. This error is not considered a substitution error (hence SFINAE),
it is an outright error. So you get a compile error just trying to
deduce the type.
The solution was to move to the C++14 version of an auto return type. In
this case, the return type is no longer important for SFINAE and is
delayed until the function is actually compiled with the specific
template parameters. This would be a problem if the const version of
`CastAndCall` was used when the non-const version was needed. But now
both versions will pass SFINAE and thus the non-const version will be
chosen as long as the `Variant` object itself is non-const. If the
`Variant` object itself is const, then that is in fact a legitimate
error, so a compile error is OK.
One thing I find wierd is that `CastAndCall` still has a `noexcept`
expression that will likewise cause a compile error in this case.
However, it is still working. I _think_ the difference is that
`noexcept` is not used to determine template substitution/overloaded, so
is therefore ignored until the function is actually compiled.
2022-07-29 12:50:34 +00:00
|
|
|
|
|
|
|
variant1.CastAndCall([](auto& object) { ++object.Value; });
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
2022-06-29 18:34:02 +00:00
|
|
|
void TestCopyInvalid()
|
|
|
|
{
|
|
|
|
std::cout << "Test copy invalid variant" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<TypePlaceholder<0>, NonTrivial>;
|
2022-06-29 18:34:02 +00:00
|
|
|
|
|
|
|
VariantType source;
|
|
|
|
source.Reset();
|
|
|
|
|
|
|
|
VariantType destination1(source);
|
|
|
|
VTKM_TEST_ASSERT(!destination1.IsValid());
|
|
|
|
|
|
|
|
VariantType destination2(TypePlaceholder<0>{});
|
|
|
|
destination2 = source;
|
|
|
|
VTKM_TEST_ASSERT(!destination2.IsValid());
|
|
|
|
}
|
|
|
|
|
2019-10-27 13:33:45 +00:00
|
|
|
struct CountConstructDestruct
|
|
|
|
{
|
|
|
|
vtkm::Id* Count;
|
|
|
|
CountConstructDestruct(vtkm::Id* count)
|
|
|
|
: Count(count)
|
|
|
|
{
|
|
|
|
++(*this->Count);
|
|
|
|
}
|
|
|
|
CountConstructDestruct(const CountConstructDestruct& src)
|
|
|
|
: Count(src.Count)
|
|
|
|
{
|
|
|
|
++(*this->Count);
|
|
|
|
}
|
|
|
|
~CountConstructDestruct() { --(*this->Count); }
|
2021-03-17 20:38:33 +00:00
|
|
|
CountConstructDestruct& operator=(const CountConstructDestruct&) = delete;
|
2019-10-27 13:33:45 +00:00
|
|
|
};
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
void TestCopyDestroy()
|
|
|
|
{
|
|
|
|
std::cout << "Test copy destroy" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<TypePlaceholder<0>,
|
|
|
|
TypePlaceholder<1>,
|
|
|
|
CountConstructDestruct,
|
|
|
|
TypePlaceholder<3>,
|
|
|
|
TypePlaceholder<4>>;
|
2021-03-24 20:41:31 +00:00
|
|
|
#ifdef VTKM_USE_STD_IS_TRIVIAL
|
2021-04-01 20:47:51 +00:00
|
|
|
VTKM_STATIC_ASSERT(!vtkmstd::is_trivially_copyable<VariantType>::value);
|
|
|
|
#endif // VTKM_USE_STD_IS_TRIVIAL
|
2019-07-14 23:38:30 +00:00
|
|
|
vtkm::Id count = 0;
|
|
|
|
|
|
|
|
VariantType variant1 = CountConstructDestruct(&count);
|
|
|
|
VTKM_TEST_ASSERT(count == 1, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 1);
|
|
|
|
|
|
|
|
{
|
|
|
|
VariantType variant2{ variant1 };
|
|
|
|
VTKM_TEST_ASSERT(count == 2, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 2);
|
|
|
|
VTKM_TEST_ASSERT(*variant2.Get<2>().Count == 2);
|
|
|
|
}
|
|
|
|
VTKM_TEST_ASSERT(count == 1, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 1);
|
|
|
|
|
|
|
|
{
|
|
|
|
VariantType variant3{ VariantType(CountConstructDestruct(&count)) };
|
|
|
|
VTKM_TEST_ASSERT(count == 2, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 2);
|
|
|
|
VTKM_TEST_ASSERT(*variant3.Get<2>().Count == 2);
|
|
|
|
}
|
|
|
|
VTKM_TEST_ASSERT(count == 1, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 1);
|
|
|
|
|
|
|
|
{
|
|
|
|
VariantType variant4{ variant1 };
|
|
|
|
VTKM_TEST_ASSERT(count == 2, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 2);
|
|
|
|
VTKM_TEST_ASSERT(*variant4.Get<2>().Count == 2);
|
|
|
|
|
|
|
|
variant4 = TypePlaceholder<0>{};
|
|
|
|
VTKM_TEST_ASSERT(count == 1, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 1);
|
|
|
|
|
|
|
|
variant4 = VariantType{ TypePlaceholder<1>{} };
|
|
|
|
VTKM_TEST_ASSERT(count == 1, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 1);
|
|
|
|
|
|
|
|
variant4 = variant1;
|
|
|
|
VTKM_TEST_ASSERT(count == 2, count);
|
|
|
|
VTKM_TEST_ASSERT(*variant1.Get<2>().Count == 2);
|
|
|
|
VTKM_TEST_ASSERT(*variant4.Get<2>().Count == 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestEmplace()
|
|
|
|
{
|
|
|
|
std::cout << "Test Emplace" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<vtkm::Id, vtkm::Id3, std::vector<vtkm::Id>>;
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
VariantType variant;
|
|
|
|
variant.Emplace<vtkm::Id>(TestValue(0, vtkm::Id{}));
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndex() == 0);
|
|
|
|
VTKM_TEST_ASSERT(variant.Get<vtkm::Id>() == TestValue(0, vtkm::Id{}));
|
|
|
|
|
|
|
|
variant.Emplace<1>(TestValue(1, vtkm::Id{}));
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndex() == 1);
|
|
|
|
VTKM_TEST_ASSERT(variant.Get<vtkm::Id3>() == vtkm::Id3{ TestValue(1, vtkm::Id{}) });
|
|
|
|
|
|
|
|
variant.Emplace<1>(TestValue(2, vtkm::Id{}), TestValue(3, vtkm::Id{}), TestValue(4, vtkm::Id{}));
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndex() == 1);
|
2020-08-17 14:18:24 +00:00
|
|
|
VTKM_TEST_ASSERT(
|
|
|
|
variant.Get<vtkm::Id3>() ==
|
|
|
|
vtkm::Id3{ TestValue(2, vtkm::Id{}), TestValue(3, vtkm::Id{}), TestValue(4, vtkm::Id{}) });
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
variant.Emplace<2>(
|
|
|
|
{ TestValue(5, vtkm::Id{}), TestValue(6, vtkm::Id{}), TestValue(7, vtkm::Id{}) });
|
|
|
|
VTKM_TEST_ASSERT(variant.GetIndex() == 2);
|
|
|
|
VTKM_TEST_ASSERT(variant.Get<std::vector<vtkm::Id>>() ==
|
|
|
|
std::vector<vtkm::Id>{ TestValue(5, vtkm::Id{}),
|
|
|
|
TestValue(6, vtkm::Id{}),
|
|
|
|
TestValue(7, vtkm::Id{}) });
|
|
|
|
}
|
|
|
|
|
2020-10-08 18:02:27 +00:00
|
|
|
void TestConstructDestruct()
|
|
|
|
{
|
|
|
|
std::cout << "Make sure constructors and destructors are called correctly" << std::endl;
|
|
|
|
|
|
|
|
g_NonTrivialCount = 0;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<NonTrivial, TrivialCopy>;
|
2020-10-08 18:02:27 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
VariantType variant1 = NonTrivial{};
|
|
|
|
VariantType variant2 = variant1;
|
|
|
|
variant2 = NonTrivial{};
|
|
|
|
NonTrivial nonTrivial;
|
|
|
|
VariantType variant3 = nonTrivial;
|
|
|
|
VariantType variant4;
|
|
|
|
variant4.Emplace<NonTrivial>();
|
|
|
|
VariantType variant5(VariantType(NonTrivial{}));
|
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(g_NonTrivialCount == 0);
|
|
|
|
}
|
|
|
|
|
2021-03-24 20:41:31 +00:00
|
|
|
void TestCopySelf()
|
|
|
|
{
|
|
|
|
std::cout << "Make sure copying a Variant to itself works" << std::endl;
|
|
|
|
|
2022-11-01 13:52:41 +00:00
|
|
|
using VariantType = vtkm::exec::Variant<TypePlaceholder<0>, NonTrivial, TypePlaceholder<2>>;
|
2021-03-24 20:41:31 +00:00
|
|
|
|
|
|
|
VariantType variant{ NonTrivial{} };
|
|
|
|
VariantType& variantRef = variant;
|
|
|
|
variant = variantRef;
|
|
|
|
variant = variant.Get<NonTrivial>();
|
|
|
|
}
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
void RunTest()
|
|
|
|
{
|
|
|
|
TestSize();
|
|
|
|
TestIndexing();
|
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
|
|
|
TestTriviallyCopyable();
|
2019-07-14 23:38:30 +00:00
|
|
|
TestGet();
|
|
|
|
TestCastAndCall();
|
2022-06-29 18:34:02 +00:00
|
|
|
TestCopyInvalid();
|
2019-07-14 23:38:30 +00:00
|
|
|
TestCopyDestroy();
|
|
|
|
TestEmplace();
|
2020-10-08 18:02:27 +00:00
|
|
|
TestConstructDestruct();
|
2021-03-24 20:41:31 +00:00
|
|
|
TestCopySelf();
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|
|
|
|
|
2019-10-27 13:33:45 +00:00
|
|
|
} // namespace test_variant
|
2019-07-14 23:38:30 +00:00
|
|
|
|
|
|
|
int UnitTestVariant(int argc, char* argv[])
|
|
|
|
{
|
2019-10-27 13:33:45 +00:00
|
|
|
return vtkm::testing::Testing::Run(test_variant::RunTest, argc, argv);
|
2019-07-14 23:38:30 +00:00
|
|
|
}
|