Commit cbf913ad authored by Kenneth Moreland's avatar Kenneth Moreland Committed by Kitware Robot

Merge topic 'cast-variant-to-storage'

d59ce11c Allow VariantArrayHandle CastAndCall to cast to concrete types
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard's avatarRobert Maynard <robert.maynard@kitware.com>
Merge-request: !1519
parents 4003b5fc d59ce11c
# Allow VariantArrayHandle CastAndCall to cast to concrete types
Previously, the `VariantArrayHandle::CastAndCall` (and indirect calls through
`vtkm::cont::CastAndCall`) attempted to cast to only
`vtkm::cont::ArrayHandleVirtual` with different value types. That worked, but
it meant that whatever was called had to operate through virtual functions.
Under most circumstances, it is worthwhile to also check for some common
storage types that, when encountered, can be accessed much faster. This
change provides the casting to concrete storage types and now uses
`vtkm::cont::ArrayHandleVirtual` as a fallback when no concrete storage
type is found.
By default, `CastAndCall` checks all the storage types in
`VTKM_DEFAULT_STORAGE_LIST_TAG`, which typically contains only the basic
storage. The `ArrayHandleVirtual::CastAndCall` method also allows you to
override this behavior by specifying a different type list in the first
argument. If the first argument is a list type, `CastAndCall` assumes that
all the types in the list are storage tags. If you pass in
`vtkm::ListTagEmpty`, then `CastAndCall` will always cast to an
`ArrayHandleVirtual` (the previous behavior). Alternately, you can pass in
storage tags that might be likely under the current usage.
As an example, consider the following simple code.
``` cpp
vtkm::cont::VariantArrayHandle array;
// stuff happens
array.CastAndCall(myFunctor);
```
Previously, `myFunctor` would be called with
`vtkm::cont::ArrayHandleVirtual<T>` with different type `T`s. After this
change, `myFunctor` will be called with that and with
`vtkm::cont::ArrayHandle<T>` of the same type `T`s.
If you want to only call `myFunctor` with
`vtkm::cont::ArrayHandleVirtual<T>`, then replace the previous line with
``` cpp
array.CastAndCall(vtkm::ListTagEmpty(), myFunctor);
```
Let's say that additionally using `vtkm::cont::ArrayHandleIndex` was also
common. If you want to also specialize for that array, you can do so with
the following line.
``` cpp
array.CastAndCall(vtkm::ListTagBase<vtkm::cont::StorageBasic,
vtkm::cont::ArrayHandleIndex::StorageTag>,
myFunctor);
```
Note that `myFunctor` will be called with
`vtkm::cont::ArrayHandle<T,vtkm::cont::ArrayHandleIndex::StorageTag>`, not
`vtkm::cont::ArrayHandleIndex`.
...@@ -113,11 +113,10 @@ private: ...@@ -113,11 +113,10 @@ private:
template <typename T, class ArrayPortalType, class DeviceAdapterTag> template <typename T, class ArrayPortalType, class DeviceAdapterTag>
class ArrayTransfer<T, StorageTagImplicit<ArrayPortalType>, DeviceAdapterTag> class ArrayTransfer<T, StorageTagImplicit<ArrayPortalType>, DeviceAdapterTag>
{ {
private: public:
using StorageTag = StorageTagImplicit<ArrayPortalType>; using StorageTag = StorageTagImplicit<ArrayPortalType>;
using StorageType = vtkm::cont::internal::Storage<T, StorageTag>; using StorageType = vtkm::cont::internal::Storage<T, StorageTag>;
public:
using ValueType = T; using ValueType = T;
using PortalControl = typename StorageType::PortalType; using PortalControl = typename StorageType::PortalType;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <vtkm/cont/ErrorBadType.h> #include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/Logging.h> #include <vtkm/cont/Logging.h>
#include <vtkm/cont/StorageListTag.h>
#include <vtkm/cont/internal/DynamicTransform.h> #include <vtkm/cont/internal/DynamicTransform.h>
#include <vtkm/cont/internal/VariantArrayHandleContainer.h> #include <vtkm/cont/internal/VariantArrayHandleContainer.h>
...@@ -173,13 +174,45 @@ public: ...@@ -173,13 +174,45 @@ public:
return VariantArrayHandleBase<NewTypeList>(*this); return VariantArrayHandleBase<NewTypeList>(*this);
} }
/// Attempts to cast the held array to a specific value type, //@{
/// \brief Call a functor using the underlying array type.
///
/// \c CastAndCall Attempts to cast the held array to a specific value type,
/// then call the given functor with the cast array. The types /// then call the given functor with the cast array. The types
/// tried in the cast are those in the lists defined by the TypeList. /// tried in the cast are those in the lists defined by the TypeList.
/// By default \c VariantArrayHandle set this to VTKM_DEFAULT_TYPE_LIST_TAG. /// By default \c VariantArrayHandle set this to \c VTKM_DEFAULT_TYPE_LIST_TAG.
/// ///
template <typename Functor, typename... Args> /// In addition to the value type, an \c ArrayHandle also requires a storage tag.
VTKM_CONT void CastAndCall(Functor&& f, Args&&...) const; /// By default, \c CastAndCall attempts to cast the array using the storage tags
/// listed in \c VTKM_DEFAULT_STORAGE_LIST_TAG. You can optionally give a custom
/// list of storage tags as the second argument. If the storage of the underlying
/// array does not match any of the storage tags given, then the array will
/// be cast to an \c ArrayHandleVirtual, which can hold any array given the
/// appropriate value type. To always use \c ArrayHandleVirtual, pass
/// \c vtkm::ListTagEmpty as thefirst argument.
///
/// As previous stated, if a storage tag list is provided, it is given in the
/// first argument. The functor to call with the cast array is given as the next
/// argument (or the first argument if a storage tag list is not provided).
/// The remaning arguments, if any, are passed to the functor.
///
/// The functor will be called with the cast array as its first argument. Any
/// remaining arguments are passed from the arguments to \c CastAndCall.
///
template <typename FunctorOrStorageList, typename... Args>
VTKM_CONT void CastAndCall(FunctorOrStorageList&& functorOrStorageList, Args&&... args) const
{
this->CastAndCallImpl(vtkm::internal::ListTagCheck<FunctorOrStorageList>(),
std::forward<FunctorOrStorageList>(functorOrStorageList),
std::forward<Args>(args)...);
}
template <typename Functor>
VTKM_CONT void CastAndCall(Functor&& f) const
{
this->CastAndCallImpl(std::false_type(), std::forward<Functor>(f));
}
//@}
/// \brief Create a new array of the same type as this array. /// \brief Create a new array of the same type as this array.
/// ///
...@@ -228,6 +261,18 @@ public: ...@@ -228,6 +261,18 @@ public:
private: private:
friend struct internal::variant::GetContainer; friend struct internal::variant::GetContainer;
std::shared_ptr<vtkm::cont::internal::VariantArrayHandleContainerBase> ArrayContainer; std::shared_ptr<vtkm::cont::internal::VariantArrayHandleContainerBase> ArrayContainer;
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCallImpl(std::false_type, Functor&& f, Args&&... args) const
{
this->CastAndCallImpl(std::true_type(),
VTKM_DEFAULT_STORAGE_LIST_TAG(),
std::forward<Functor>(f),
std::forward<Args>(args)...);
}
template <typename StorageTagList, typename Functor, typename... Args>
VTKM_CONT void CastAndCallImpl(std::true_type, StorageTagList, Functor&& f, Args&&...) const;
}; };
using VariantArrayHandle = vtkm::cont::VariantArrayHandleBase<VTKM_DEFAULT_TYPE_LIST_TAG>; using VariantArrayHandle = vtkm::cont::VariantArrayHandleBase<VTKM_DEFAULT_TYPE_LIST_TAG>;
...@@ -254,6 +299,37 @@ namespace detail ...@@ -254,6 +299,37 @@ namespace detail
{ {
struct VariantArrayHandleTry struct VariantArrayHandleTry
{
template <typename T, typename Storage, typename Functor, typename... Args>
void operator()(brigand::list<T, Storage>,
Functor&& f,
bool& called,
const vtkm::cont::internal::VariantArrayHandleContainerBase& container,
Args&&... args) const
{
using DerivedArrayType = vtkm::cont::ArrayHandle<T, Storage>;
if (!called && vtkm::cont::internal::variant::IsType<DerivedArrayType>(&container))
{
called = true;
const auto* derivedContainer =
static_cast<const vtkm::cont::internal::VariantArrayHandleContainer<T>*>(&container);
DerivedArrayType derivedArray = derivedContainer->Array.template Cast<DerivedArrayType>();
VTKM_LOG_CAST_SUCC(container, derivedArray);
// If you get a compile error here, it means that you have called CastAndCall for a
// vtkm::cont::VariantArrayHandle and the arguments of the functor do not match those
// being passed. This is often because it is calling the functor with an ArrayHandle
// type that was not expected. Either add overloads to the functor to accept all
// possible array types or constrain the types tried for the CastAndCall. Note that
// the functor will be called with an array of type vtkm::cont::ArrayHandle<T, S>.
// Directly using a subclass of ArrayHandle (e.g. vtkm::cont::ArrayHandleConstant<T>)
// might not work.
f(derivedArray, std::forward<Args>(args)...);
}
}
};
struct VariantArrayHandleTryFallback
{ {
template <typename T, typename Functor, typename... Args> template <typename T, typename Functor, typename... Args>
void operator()(T, void operator()(T,
...@@ -268,31 +344,74 @@ struct VariantArrayHandleTry ...@@ -268,31 +344,74 @@ struct VariantArrayHandleTry
const auto* derived = const auto* derived =
static_cast<const vtkm::cont::internal::VariantArrayHandleContainer<T>*>(&container); static_cast<const vtkm::cont::internal::VariantArrayHandleContainer<T>*>(&container);
VTKM_LOG_CAST_SUCC(container, derived); VTKM_LOG_CAST_SUCC(container, derived);
// If you get a compile error here, it means that you have called CastAndCall for a
// vtkm::cont::VariantArrayHandle and the arguments of the functor do not match those
// being passed. This is often because it is calling the functor with an ArrayHandle
// type that was not expected. Either add overloads to the functor to accept all
// possible array types or constrain the types tried for the CastAndCall. Note that
// the functor will be called with an array of type vtkm::cont::ArrayHandle<T, S>.
// Directly using a subclass of ArrayHandle (e.g. vtkm::cont::ArrayHandleConstant<T>)
// might not work.
f(derived->Array, std::forward<Args>(args)...); f(derived->Array, std::forward<Args>(args)...);
} }
} }
}; };
template <typename T>
struct IsUndefinedStorage
{
};
template <typename T, typename U>
struct IsUndefinedStorage<brigand::list<T, U>> : vtkm::cont::internal::IsInValidArrayHandle<T, U>
{
};
template <typename TypeList, typename StorageList>
struct ListTagDynamicTypes : vtkm::detail::ListRoot
{
using crossProduct = typename vtkm::ListCrossProduct<TypeList, StorageList>;
// using list = typename crossProduct::list;
using list = ::brigand::remove_if<typename crossProduct::list, IsUndefinedStorage<brigand::_1>>;
};
VTKM_CONT_EXPORT void ThrowCastAndCallException( VTKM_CONT_EXPORT void ThrowCastAndCallException(
const vtkm::cont::internal::VariantArrayHandleContainerBase&, const vtkm::cont::internal::VariantArrayHandleContainerBase&,
const std::type_info&); const std::type_info&);
} // namespace detail } // namespace detail
template <typename TypeList> template <typename TypeList>
template <typename Functor, typename... Args> template <typename StorageTagList, typename Functor, typename... Args>
VTKM_CONT void VariantArrayHandleBase<TypeList>::CastAndCall(Functor&& f, Args&&... args) const VTKM_CONT void VariantArrayHandleBase<TypeList>::CastAndCallImpl(std::true_type,
StorageTagList,
Functor&& f,
Args&&... args) const
{ {
using crossProduct = detail::ListTagDynamicTypes<TypeList, StorageTagList>;
bool called = false; bool called = false;
const auto& ref = *this->ArrayContainer; const auto& ref = *this->ArrayContainer;
vtkm::ListForEach(detail::VariantArrayHandleTry{}, vtkm::ListForEach(detail::VariantArrayHandleTry{},
TypeList{}, crossProduct{},
std::forward<Functor>(f), std::forward<Functor>(f),
called, called,
ref, ref,
std::forward<Args>(args)...); std::forward<Args>(args)...);
if (!called) if (!called)
{
// try to fall back to using ArrayHandleVirtual
vtkm::ListForEach(detail::VariantArrayHandleTryFallback{},
TypeList{},
std::forward<Functor>(f),
called,
ref,
std::forward<Args>(args)...);
}
if (!called)
{ {
// throw an exception // throw an exception
VTKM_LOG_CAST_FAIL(*this, TypeList); VTKM_LOG_CAST_FAIL(*this, TypeList);
...@@ -363,7 +482,7 @@ private: ...@@ -363,7 +482,7 @@ private:
public: public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& obj) static VTKM_CONT void save(BinaryBuffer& bb, const Type& obj)
{ {
vtkm::cont::CastAndCall(obj, internal::VariantArrayHandleSerializeFunctor{}, bb); obj.CastAndCall(vtkm::ListTagEmpty(), internal::VariantArrayHandleSerializeFunctor{}, bb);
} }
static VTKM_CONT void load(BinaryBuffer& bb, Type& obj) static VTKM_CONT void load(BinaryBuffer& bb, Type& obj)
......
...@@ -70,8 +70,8 @@ struct ScalarFunctor ...@@ -70,8 +70,8 @@ struct ScalarFunctor
struct ArrayHandleScalarFunctor struct ArrayHandleScalarFunctor
{ {
template <typename T> template <typename ArrayType>
void operator()(const vtkm::cont::ArrayHandleVirtual<T>&) const void operator()(const ArrayType&) const
{ {
VTKM_TEST_FAIL("Called wrong form of functor operator."); VTKM_TEST_FAIL("Called wrong form of functor operator.");
} }
......
...@@ -95,12 +95,6 @@ public: ...@@ -95,12 +95,6 @@ public:
} }
}; };
struct StorageListTagUnusual
: vtkm::ListTagBase<ArrayHandleWithUnusualStorage<vtkm::Id>::StorageTag,
ArrayHandleWithUnusualStorage<std::string>::StorageTag>
{
};
template <typename T> template <typename T>
struct TestValueFunctor struct TestValueFunctor
{ {
...@@ -110,10 +104,44 @@ struct TestValueFunctor ...@@ -110,10 +104,44 @@ struct TestValueFunctor
struct CheckFunctor struct CheckFunctor
{ {
template <typename T> template <typename T>
void operator()(const vtkm::cont::ArrayHandleVirtual<T>& array, bool& called) const void operator()(const vtkm::cont::ArrayHandle<T>& array,
bool& calledBasic,
bool& vtkmNotUsed(calledUnusual),
bool& vtkmNotUsed(calledVirtual)) const
{
calledBasic = true;
std::cout << " Checking for basic array type: " << typeid(T).name() << std::endl;
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size.");
auto portal = array.GetPortalConstControl();
CheckPortal(portal);
}
template <typename T>
void operator()(
const vtkm::cont::ArrayHandle<T, typename ArrayHandleWithUnusualStorage<T>::StorageTag>& array,
bool& vtkmNotUsed(calledBasic),
bool& calledUnusual,
bool& vtkmNotUsed(calledVirtual)) const
{
calledUnusual = true;
std::cout << " Checking for unusual array type: " << typeid(T).name() << std::endl;
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size.");
auto portal = array.GetPortalConstControl();
CheckPortal(portal);
}
template <typename T>
void operator()(const vtkm::cont::ArrayHandleVirtual<T>& array,
bool& vtkmNotUsed(calledBasic),
bool& vtkmNotUsed(calledUnusual),
bool& calledVirtual) const
{ {
called = true; calledVirtual = true;
std::cout << " Checking for type: " << typeid(T).name() << std::endl; std::cout << " Checking for virtual array type: " << typeid(T).name() << std::endl;
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size."); VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size.");
...@@ -132,28 +160,78 @@ void BasicArrayVariantChecks(const vtkm::cont::VariantArrayHandleBase<TypeList>& ...@@ -132,28 +160,78 @@ void BasicArrayVariantChecks(const vtkm::cont::VariantArrayHandleBase<TypeList>&
"Dynamic array reports unexpected number of components."); "Dynamic array reports unexpected number of components.");
} }
void CheckArrayVariant(vtkm::cont::VariantArrayHandle array, vtkm::IdComponent numComponents)
{
BasicArrayVariantChecks(array, numComponents);
bool called = false;
array.CastAndCall(CheckFunctor(), called);
VTKM_TEST_ASSERT(
called, "The functor was never called (and apparently a bad value exception not thrown).");
}
template <typename TypeList> template <typename TypeList>
void CheckArrayVariant(const vtkm::cont::VariantArrayHandleBase<TypeList>& array, void CheckArrayVariant(const vtkm::cont::VariantArrayHandleBase<TypeList>& array,
vtkm::IdComponent numComponents) vtkm::IdComponent numComponents,
bool isBasicArray,
bool isUnusualArray)
{ {
BasicArrayVariantChecks(array, numComponents); BasicArrayVariantChecks(array, numComponents);
bool called = false; std::cout << " CastAndCall with default storage" << std::endl;
CastAndCall(array, CheckFunctor(), called); bool calledBasic = false;
bool calledUnusual = false;
bool calledVirtual = false;
CastAndCall(array, CheckFunctor(), calledBasic, calledUnusual, calledVirtual);
VTKM_TEST_ASSERT(
calledBasic || calledUnusual || calledVirtual,
"The functor was never called (and apparently a bad value exception not thrown).");
if (isBasicArray)
{
VTKM_TEST_ASSERT(calledBasic, "The functor was never called with the basic array fast path");
VTKM_TEST_ASSERT(!calledUnusual, "The functor was somehow called with the unusual fast path");
VTKM_TEST_ASSERT(!calledVirtual, "The functor was somehow called with the virtual path");
}
else
{
VTKM_TEST_ASSERT(!calledBasic, "The array somehow got cast to a basic storage.");
VTKM_TEST_ASSERT(!calledUnusual, "The array somehow got cast to an unusual storage.");
}
std::cout << " CastAndCall with no storage" << std::endl;
calledBasic = false;
calledUnusual = false;
calledVirtual = false;
array.CastAndCall(
vtkm::ListTagEmpty(), CheckFunctor(), calledBasic, calledUnusual, calledVirtual);
VTKM_TEST_ASSERT( VTKM_TEST_ASSERT(
called, "The functor was never called (and apparently a bad value exception not thrown)."); calledBasic || calledUnusual || calledVirtual,
"The functor was never called (and apparently a bad value exception not thrown).");
VTKM_TEST_ASSERT(!calledBasic, "The array somehow got cast to a basic storage.");
VTKM_TEST_ASSERT(!calledUnusual, "The array somehow got cast to an unusual storage.");
std::cout << " CastAndCall with extra storage" << std::endl;
calledBasic = false;
calledUnusual = false;
calledVirtual = false;
array.CastAndCall(vtkm::ListTagBase<vtkm::cont::StorageTagBasic,
ArrayHandleWithUnusualStorage<vtkm::Id>::StorageTag,
ArrayHandleWithUnusualStorage<std::string>::StorageTag>(),
CheckFunctor(),
calledBasic,
calledUnusual,
calledVirtual);
VTKM_TEST_ASSERT(
calledBasic || calledUnusual || calledVirtual,
"The functor was never called (and apparently a bad value exception not thrown).");
if (isBasicArray)
{
VTKM_TEST_ASSERT(calledBasic, "The functor was never called with the basic array fast path");
VTKM_TEST_ASSERT(!calledUnusual, "The functor was somehow called with the unusual fast path");
VTKM_TEST_ASSERT(!calledVirtual, "The functor was somehow called with the virtual path");
}
else if (isUnusualArray)
{
VTKM_TEST_ASSERT(calledUnusual, "The functor was never called with the unusual fast path");
VTKM_TEST_ASSERT(!calledBasic, "The functor was somehow called with the basic fast path");
VTKM_TEST_ASSERT(!calledVirtual, "The functor was somehow called with the virtual path");
}
else
{
VTKM_TEST_ASSERT(!calledBasic, "The array somehow got cast to a basic storage.");
VTKM_TEST_ASSERT(!calledUnusual, "The array somehow got cast to an unusual storage.");
}
} }
template <typename T> template <typename T>
...@@ -196,7 +274,7 @@ template <typename T, typename ArrayVariantType> ...@@ -196,7 +274,7 @@ template <typename T, typename ArrayVariantType>
void TryNewInstance(T, ArrayVariantType originalArray) void TryNewInstance(T, ArrayVariantType originalArray)
{ {
// This check should already have been performed by caller, but just in case. // This check should already have been performed by caller, but just in case.
CheckArrayVariant(originalArray, vtkm::VecTraits<T>::NUM_COMPONENTS); CheckArrayVariant(originalArray, vtkm::VecTraits<T>::NUM_COMPONENTS, true, false);
std::cout << "Create new instance of array." << std::endl; std::cout << "Create new instance of array." << std::endl;
ArrayVariantType newArray = originalArray.NewInstance(); ArrayVariantType newArray = originalArray.NewInstance();
...@@ -212,7 +290,7 @@ void TryNewInstance(T, ArrayVariantType originalArray) ...@@ -212,7 +290,7 @@ void TryNewInstance(T, ArrayVariantType originalArray)
{ {
staticArray.GetPortalControl().Set(index, TestValue(index + 100, T())); staticArray.GetPortalControl().Set(index, TestValue(index + 100, T()));
} }
CheckArrayVariant(originalArray, vtkm::VecTraits<T>::NUM_COMPONENTS); CheckArrayVariant(originalArray, vtkm::VecTraits<T>::NUM_COMPONENTS, true, false);
std::cout << "Set the new static array to expected values and make sure the new" << std::endl std::cout << "Set the new static array to expected values and make sure the new" << std::endl
<< "dynamic array points to the same new values." << std::endl; << "dynamic array points to the same new values." << std::endl;
...@@ -220,7 +298,7 @@ void TryNewInstance(T, ArrayVariantType originalArray) ...@@ -220,7 +298,7 @@ void TryNewInstance(T, ArrayVariantType originalArray)
{ {
staticArray.GetPortalControl().Set(index, TestValue(index, T())); staticArray.GetPortalControl().Set(index, TestValue(index, T()));
} }
CheckArrayVariant(newArray, vtkm::VecTraits<T>::NUM_COMPONENTS); CheckArrayVariant(newArray, vtkm::VecTraits<T>::NUM_COMPONENTS, true, false);
} }
template <typename T> template <typename T>
...@@ -228,7 +306,7 @@ void TryDefaultType(T) ...@@ -228,7 +306,7 @@ void TryDefaultType(T)
{ {
vtkm::cont::VariantArrayHandle array = CreateArrayVariant(T()); vtkm::cont::VariantArrayHandle array = CreateArrayVariant(T());
CheckArrayVariant(array, vtkm::VecTraits<T>::NUM_COMPONENTS); CheckArrayVariant(array, vtkm::VecTraits<T>::NUM_COMPONENTS, true, false);
TryNewInstance(T(), array); TryNewInstance(T(), array);
} }
...@@ -240,7 +318,8 @@ struct TryBasicVTKmType ...@@ -240,7 +318,8 @@ struct TryBasicVTKmType
{ {
vtkm::cont::VariantArrayHandle array = CreateArrayVariant(T()); vtkm::cont::VariantArrayHandle array = CreateArrayVariant(T());
CheckArrayVariant(array.ResetTypes(vtkm::TypeListTagAll()), vtkm::VecTraits<T>::NUM_COMPONENTS); CheckArrayVariant(
array.ResetTypes(vtkm::TypeListTagAll()), vtkm::VecTraits<T>::NUM_COMPONENTS, true, false);
TryNewInstance(T(), array.ResetTypes(vtkm::TypeListTagAll())); TryNewInstance(T(), array.ResetTypes(vtkm::TypeListTagAll()));
} }
...@@ -253,7 +332,7 @@ void TryUnusualType() ...@@ -253,7 +332,7 @@ void TryUnusualType()
try try
{ {
CheckArrayVariant(array, 1); CheckArrayVariant(array, 1, true, false);
VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized type."); VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized type.");
} }
catch (vtkm::cont::ErrorBadValue&) catch (vtkm::cont::ErrorBadValue&)
...@@ -261,7 +340,7 @@ void TryUnusualType() ...@@ -261,7 +340,7 @@ void TryUnusualType()
std::cout << " Caught exception for unrecognized type." << std::endl; std::cout << " Caught exception for unrecognized type." << std::endl;
} }
CheckArrayVariant(array.ResetTypes(TypeListTagString()), 1); CheckArrayVariant(array.ResetTypes(TypeListTagString()), 1, true, false);
std::cout << " Found type when type list was reset." << std::endl; std::cout << " Found type when type list was reset." << std::endl;
} }
...@@ -271,7 +350,7 @@ void TryUnusualStorage() ...@@ -271,7 +350,7 @@ void TryUnusualStorage()
try try
{ {
CheckArrayVariant(array, 1); CheckArrayVariant(array, 1, false, true);
} }
catch (...) catch (...)
{ {
...@@ -285,7 +364,7 @@ void TryUnusualTypeAndStorage() ...@@ -285,7 +364,7 @@ void TryUnusualTypeAndStorage()
try try
{ {
CheckArrayVariant(array, 1); CheckArrayVariant(array, 1, false, true);
VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized type/storage."); VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized type/storage.");
} }
catch (vtkm::cont::ErrorBadValue&) catch (vtkm::cont::ErrorBadValue&)
...@@ -295,7 +374,7 @@ void TryUnusualTypeAndStorage() ...@@ -295,7 +374,7 @@ void TryUnusualTypeAndStorage()
try try
{ {
CheckArrayVariant(array.ResetTypes(TypeListTagString()), 1); CheckArrayVariant(array.ResetTypes(TypeListTagString()), 1, false, true);
} }
catch (...) catch (...)
{ {
......
...@@ -852,11 +852,16 @@ private: ...@@ -852,11 +852,16 @@ private:
{ {
} }
template <typename T> template <typename ArrayHandleType>
void operator()(const vtkm::cont::ArrayHandleVirtual<T>& handle) const void operator()(const ArrayHandleType& handle) const
{ {
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
using T = typename ArrayHandleType::ValueType;
if (this->Permutation.GetNumberOfValues() < 1) if (this->Permutation.GetNumberOfValues() < 1)
{
return; return;
}
vtkm::cont::ArrayHandle<T> out; vtkm::cont::ArrayHandle<T> out;
out.Allocate(this->Permutation.GetNumberOfValues()); out.Allocate(this->Permutation.GetNumberOfValues());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment