Implement VecTraits class for all types

The `VecTraits` class allows templated functions, methods, and classes to
treat type arguments uniformly as `Vec` types or to otherwise differentiate
between scalar and vector types. This only works for types that `VecTraits`
is defined for.

The `VecTraits` templated class now has a default implementation that will
be used for any type that does not have a `VecTraits` specialization. This
removes many surprise compiler errors when using a template that, unknown
to you, has `VecTraits` in its implementation.

One potential issue is that if `VecTraits` gets defined for a new type, the
behavior of `VecTraits` could change for that type in backward-incompatible
ways. If `VecTraits` is used in a purely generic way, this should not be an
issue. However, if assumptions were made about the components and length,
this could cause problems.

Fixes #589
This commit is contained in:
Kenneth Moreland 2023-03-16 11:00:47 -06:00
parent ea5cb10eb1
commit ac889b5004
21 changed files with 291 additions and 333 deletions

@ -0,0 +1,19 @@
# Implemented `VecTraits` class for all types
The `VecTraits` class allows templated functions, methods, and classes to
treat type arguments uniformly as `Vec` types or to otherwise differentiate
between scalar and vector types. This only works for types that `VecTraits`
is defined for.
The `VecTraits` templated class now has a default implementation that will
be used for any type that does not have a `VecTraits` specialization. This
removes many surprise compiler errors when using a template that, unknown
to you, has `VecTraits` in its implementation.
One potential issue is that if `VecTraits` gets defined for a new type, the
behavior of `VecTraits` could change for that type in backward-incompatible
ways. If `VecTraits` is used in a purely generic way, this should not be an
issue. However, if assumptions were made about the components and length,
this could cause problems.
Fixes #589.

@ -69,7 +69,7 @@ public:
/// \brief A tag to determine whether the type has multiple components.
///
/// This tag is either TypeTraitsScalarTag or TypeTraitsVectorTag. Scalars can
/// also be treated as vectors.
/// also be treated as vectors with VecTraits.
using DimensionalityTag = vtkm::TypeTraitsUnknownTag;
VTKM_EXEC_CONT static T ZeroInitialization() { return T(); }

@ -22,20 +22,18 @@ namespace internal
{
template <typename T,
typename MultipleComponents =
typename vtkm::internal::SafeVecTraits<T>::HasMultipleComponents>
typename MultipleComponents = typename vtkm::VecTraits<T>::HasMultipleComponents>
struct TotalNumComponents;
template <typename T>
struct TotalNumComponents<T, vtkm::VecTraitsTagMultipleComponents>
{
VTKM_STATIC_ASSERT_MSG(
(std::is_same<typename vtkm::internal::SafeVecTraits<T>::IsSizeStatic,
vtkm::VecTraitsTagSizeStatic>::value),
(std::is_same<typename vtkm::VecTraits<T>::IsSizeStatic, vtkm::VecTraitsTagSizeStatic>::value),
"vtkm::VecFlat can only be used with Vec types with a static number of components.");
using ComponentType = typename vtkm::internal::SafeVecTraits<T>::ComponentType;
using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
static constexpr vtkm::IdComponent value =
vtkm::internal::SafeVecTraits<T>::NUM_COMPONENTS * TotalNumComponents<ComponentType>::value;
vtkm::VecTraits<T>::NUM_COMPONENTS * TotalNumComponents<ComponentType>::value;
};
template <typename T>
@ -45,7 +43,7 @@ struct TotalNumComponents<T, vtkm::VecTraitsTagSingleComponent>
};
template <typename T>
using FlattenVec = vtkm::Vec<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType,
using FlattenVec = vtkm::Vec<typename vtkm::VecTraits<T>::BaseComponentType,
vtkm::internal::TotalNumComponents<T>::value>;
template <typename T>
@ -64,10 +62,10 @@ VTKM_EXEC_CONT T GetFlatVecComponentImpl(const T& component,
}
template <typename T>
VTKM_EXEC_CONT typename vtkm::internal::SafeVecTraits<T>::BaseComponentType
VTKM_EXEC_CONT typename vtkm::VecTraits<T>::BaseComponentType
GetFlatVecComponentImpl(const T& vec, vtkm::IdComponent index, std::false_type vtkmNotUsed(isBase))
{
using Traits = vtkm::internal::SafeVecTraits<T>;
using Traits = vtkm::VecTraits<T>;
using ComponentType = typename Traits::ComponentType;
using BaseComponentType = typename Traits::BaseComponentType;
@ -80,7 +78,7 @@ GetFlatVecComponentImpl(const T& vec, vtkm::IdComponent index, std::false_type v
} // namespace detail
template <typename T>
VTKM_EXEC_CONT typename vtkm::internal::SafeVecTraits<T>::BaseComponentType GetFlatVecComponent(
VTKM_EXEC_CONT typename vtkm::VecTraits<T>::BaseComponentType GetFlatVecComponent(
const T& vec,
vtkm::IdComponent index)
{
@ -114,7 +112,7 @@ VTKM_EXEC_CONT void CopyVecNestedToFlatImpl(const NestedVecType& nestedVec,
vtkm::Vec<T, N>& flatVec,
vtkm::IdComponent flatOffset)
{
using Traits = vtkm::internal::SafeVecTraits<NestedVecType>;
using Traits = vtkm::VecTraits<NestedVecType>;
using ComponentType = typename Traits::ComponentType;
constexpr vtkm::IdComponent subSize = TotalNumComponents<ComponentType>::value;
@ -176,7 +174,7 @@ VTKM_EXEC_CONT void CopyVecFlatToNestedImpl(const vtkm::Vec<T, N>& flatVec,
vtkm::IdComponent flatOffset,
NestedVecType& nestedVec)
{
using Traits = vtkm::internal::SafeVecTraits<NestedVecType>;
using Traits = vtkm::VecTraits<NestedVecType>;
using ComponentType = typename Traits::ComponentType;
constexpr vtkm::IdComponent subSize = TotalNumComponents<ComponentType>::value;

@ -117,8 +117,7 @@ struct VecTraits<vtkm::VecFromPortal<PortalType>>
using VecType = vtkm::VecFromPortal<PortalType>;
using ComponentType = typename VecType::ComponentType;
using BaseComponentType =
typename vtkm::internal::SafeVecTraits<ComponentType>::BaseComponentType;
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeVariable;

@ -10,6 +10,8 @@
#ifndef vtk_m_VecTraits_h
#define vtk_m_VecTraits_h
#include <vtkm/Deprecated.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/Types.h>
namespace vtkm
@ -42,64 +44,55 @@ struct VecTraitsTagSizeVariable
{
};
namespace internal
{
// Forward declaration
template <typename T>
struct SafeVecTraits;
template <vtkm::IdComponent numComponents, typename ComponentType>
struct VecTraitsMultipleComponentChooser
{
using Type = vtkm::VecTraitsTagMultipleComponents;
};
template <typename ComponentType>
struct VecTraitsMultipleComponentChooser<1, ComponentType>
{
using Type = typename vtkm::internal::SafeVecTraits<ComponentType>::HasMultipleComponents;
};
} // namespace internal
/// The VecTraits class gives several static members that define how
/// to use a given type as a vector.
/// \brief Traits that can be queried to treat any type as a `Vec`.
///
template <class VecType>
/// The VecTraits class gives several static members that define how
/// to use a given type as a vector. This is useful for templated
/// functions and methods that have a parameter that could be either
/// a standard scalar type or a `Vec` or some other `Vec`-like
/// object. When using this class, scalar objects are treated like
/// a `Vec` of size 1.
///
/// The default implementation of this template treats the type as
/// a scalar. Types that actually behave like vectors should
/// specialize this template to provide the proper information.
///
template <class T>
struct VTKM_NEVER_EXPORT VecTraits
{
#ifdef VTKM_DOXYGEN_ONLY
// The base VecTraits should not be used with qualifiers.
VTKM_STATIC_ASSERT_MSG((std::is_same<std::remove_pointer_t<std::decay_t<T>>, T>::value),
"The base VecTraits should not be used with qualifiers.");
/// \brief Type of the components in the vector.
///
/// If the type is really a scalar, then the component type is the same as the scalar type.
///
using ComponentType = typename VecType::ComponentType;
using ComponentType = T;
/// \brief Base component type in the vector.
///
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it
/// returns the base scalar type at the end of the composition (T in this example).
///
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
using BaseComponentType = T;
/// \brief Number of components in the vector.
///
/// This is only defined for vectors of a static size.
///
static constexpr vtkm::IdComponent NUM_COMPONENTS = VecType::NUM_COMPONENTS;
static constexpr vtkm::IdComponent NUM_COMPONENTS = 1;
/// Number of components in the given vector.
///
static vtkm::IdComponent GetNumberOfComponents(const VecType& vec);
static constexpr vtkm::IdComponent GetNumberOfComponents(const T&) { return NUM_COMPONENTS; }
/// \brief A tag specifying whether this vector has multiple components (i.e. is a "real" vector).
///
/// This tag can be useful for creating specialized functions when a vector
/// is really just a scalar.
///
using HasMultipleComponents =
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS, ComponentType>::Type;
using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent;
/// \brief A tag specifying whether the size of this vector is known at compile time.
///
@ -111,81 +104,113 @@ struct VTKM_NEVER_EXPORT VecTraits
/// Returns the value in a given component of the vector.
///
VTKM_EXEC_CONT static const ComponentType& GetComponent(
const typename std::remove_const<VecType>::type& vector,
vtkm::IdComponent component);
VTKM_EXEC_CONT static ComponentType& GetComponent(
typename std::remove_const<VecType>::type& vector,
vtkm::IdComponent component);
VTKM_EXEC_CONT static const ComponentType& GetComponent(const T& vector,
vtkm::IdComponent vtkmNotUsed(component))
{
return vector;
}
VTKM_EXEC_CONT static ComponentType& GetComponent(T& vector,
vtkm::IdComponent vtkmNotUsed(component))
{
return vector;
}
/// Changes the value in a given component of the vector.
///
VTKM_EXEC_CONT static void SetComponent(VecType& vector,
vtkm::IdComponent component,
ComponentType value);
VTKM_EXEC_CONT static void SetComponent(T& vector,
vtkm::IdComponent vtkmNotUsed(component),
ComponentType value)
{
vector = value;
}
/// \brief Get a vector of the same type but with a different component.
///
/// This type resolves to another vector with a different component type. For example,
/// @code vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> @endcode is vtkm::Vec<T2, N>.
/// This replacement is not recursive. So @code VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> @endcode
/// is vtkm::Vec<T2, N>.
/// `vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2>` is `vtkm::Vec<T2, N>`.
/// This replacement is not recursive. So `VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>`
/// is `vtkm::Vec<T2, N>`.
///
template <typename NewComponentType>
using ReplaceComponentType = VecTemplate<NewComponentType, N>;
using ReplaceComponentType = NewComponentType;
/// \brief Get a vector of the same type but with a different base component.
///
/// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example,
/// @code VecTraits<Vec<Vec<T, M>, N>::ReplaceBaseComponentType<T2> @endcode is Vec<Vec<T2, M>, N>.
/// `VecTraits<Vec<Vec<T, M>, N>::ReplaceBaseComponentType<T2>` is `Vec<Vec<T2, M>, N>`.
///
template <typename NewComponentType>
using ReplaceBaseComponentType = VecTemplate<
typename VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
N>;
using ReplaceBaseComponentType = NewComponentType;
/// Copies the components in the given vector into a given Vec object.
///
template <vktm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest);
#endif // VTKM_DOXYGEN_ONLY
template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const T& src, vtkm::Vec<ComponentType, destSize>& dest)
{
dest[0] = src;
}
};
namespace detail
{
template <typename T>
struct HasVecTraitsImpl
{
template <typename A, typename S = typename vtkm::VecTraits<A>::ComponentType>
static std::true_type Test(A*);
using HasVecTraits VTKM_DEPRECATED(2.1, "All types now have VecTraits defined.") = std::true_type;
static std::false_type Test(...);
using Type = decltype(Test(std::declval<T*>()));
};
} // namespace detail
/// \brief Determines whether the given type has VecTraits defined.
///
/// If the given type T has a valid VecTraits class, then HasVecTraits<T> will be set to
/// std::true_type. Otherwise it will be set to std::false_type. For example,
/// HasVecTraits<vtkm::Id> is the same as std::true_type whereas HasVecTraits<void *> is the same
/// as std::false_type. This is useful to block the definition of methods using VecTraits when
/// VecTraits are not defined.
///
template <typename T>
using HasVecTraits = typename detail::HasVecTraitsImpl<T>::Type;
// This partial specialization allows you to define a non-const version of
// VecTraits and have it still work for const version.
//
// These partial specializations allow VecTraits to work with const and reference qualifiers.
template <typename T>
struct VTKM_NEVER_EXPORT VecTraits<const T> : VecTraits<T>
{
};
template <typename T>
struct VTKM_NEVER_EXPORT VecTraits<T&> : VecTraits<T>
{
};
template <typename T>
struct VTKM_NEVER_EXPORT VecTraits<const T&> : VecTraits<T>
{
};
// This partial specialization allows VecTraits to work with pointers.
template <typename T>
struct VTKM_NEVER_EXPORT VecTraits<T*> : VecTraits<T>
{
VTKM_EXEC_CONT static vtkm::IdComponent GetNumberOfComponents(const T* vector)
{
return VecTraits<T>::GetNumberOfComponents(*vector);
}
VTKM_EXEC_CONT static auto GetComponent(const T* vector, vtkm::IdComponent component)
-> decltype(VecTraits<T>::GetComponent(*vector, component))
{
return VecTraits<T>::GetComponent(*vector, component);
}
VTKM_EXEC_CONT static auto GetComponent(T* vector, vtkm::IdComponent component)
-> decltype(VecTraits<T>::GetComponent(*vector, component))
{
return VecTraits<T>::GetComponent(*vector, component);
}
VTKM_EXEC_CONT static void SetComponent(T* vector,
vtkm::IdComponent component,
typename VecTraits<T>::ComponentType value)
{
VecTraits<T>::SetComponent(*vector, component, value);
}
template <typename NewComponentType>
using ReplaceComponentType =
typename VecTraits<T>::template ReplaceComponentType<NewComponentType>*;
template <typename NewComponentType>
using ReplaceBaseComponentType =
typename VecTraits<T>::template ReplaceBaseComponentType<NewComponentType>*;
template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(
const T* src,
vtkm::Vec<typename VecTraits<T>::ComponentType, destSize>& dest)
{
VecTraits<T>::CopyInto(*src, dest);
}
};
template <typename T>
struct VTKM_NEVER_EXPORT VecTraits<const T*> : VecTraits<T*>
{
};
#if defined(VTKM_GCC) && (__GNUC__ <= 5)
namespace detail
@ -201,13 +226,29 @@ template <typename T, vtkm::IdComponent Size, typename NewT>
struct VecReplaceBaseComponentTypeGCC4or5
{
using type =
vtkm::Vec<typename vtkm::internal::SafeVecTraits<T>::template ReplaceBaseComponentType<NewT>,
Size>;
vtkm::Vec<typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<NewT>, Size>;
};
} // namespace detail
#endif // GCC Version 4.8
namespace internal
{
template <vtkm::IdComponent numComponents, typename ComponentType>
struct VecTraitsMultipleComponentChooser
{
using Type = vtkm::VecTraitsTagMultipleComponents;
};
template <typename ComponentType>
struct VecTraitsMultipleComponentChooser<1, ComponentType>
{
using Type = typename vtkm::VecTraits<ComponentType>::HasMultipleComponents;
};
} // namespace internal
template <typename T, vtkm::IdComponent Size>
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
{
@ -224,8 +265,7 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it
/// returns the base scalar type at the end of the composition (T in this example).
///
using BaseComponentType =
typename vtkm::internal::SafeVecTraits<ComponentType>::BaseComponentType;
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
/// Number of components in the vector.
///
@ -304,10 +344,9 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
typename detail::VecReplaceBaseComponentTypeGCC4or5<T, Size, NewComponentType>::type;
#else // !GCC <= 5
template <typename NewComponentType>
using ReplaceBaseComponentType =
vtkm::Vec<typename vtkm::internal::SafeVecTraits<
ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
Size>;
using ReplaceBaseComponentType = vtkm::Vec<
typename vtkm::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
Size>;
#endif
///@}
@ -509,7 +548,8 @@ namespace internal
/// Used for overriding VecTraits for basic scalar types.
///
template <typename ScalarType>
struct VTKM_NEVER_EXPORT VecTraitsBasic
struct VTKM_DEPRECATED(2.1, "VecTraitsBasic is now the default implementation for VecTraits.")
VTKM_NEVER_EXPORT VecTraitsBasic
{
using ComponentType = ScalarType;
using BaseComponentType = ScalarType;
@ -548,87 +588,41 @@ struct VTKM_NEVER_EXPORT VecTraitsBasic
}
};
namespace detail
{
template <typename T, typename = vtkm::HasVecTraits<T>>
struct VTKM_NEVER_EXPORT SafeVecTraitsImpl;
template <typename T>
struct VTKM_NEVER_EXPORT SafeVecTraitsImpl<T, std::true_type> : vtkm::VecTraits<T>
{
};
template <typename T>
struct VTKM_NEVER_EXPORT SafeVecTraitsImpl<T, std::false_type> : vtkm::internal::VecTraitsBasic<T>
{
};
} // namespace detail
/// \brief A version of VecTraits that will be available for any type.
///
/// The `VecTraits` template is only defined for types that have a specific specialization
/// for it. That means if you use `VecTraits` in a template, that template will likely
/// fail to build for types that are not defined for `VecTraits`.
///
/// To use `VecTraits` in a class that should support all types, not just those with
/// defined `VecTraits`, you can use this "safe" version. `SafeVecTraits` is the same as
/// `VecTraits` if the latter is defined. If the `VecTraits` are not defined, then
/// `SafeVecTraits` treats the type as a simple scalar value.
///
/// This template ensures that it will work reasonably well for all types. But be careful
/// as if `VecTraits` is later defined, the template is likely to change.
///
template <typename T>
struct VTKM_NEVER_EXPORT SafeVecTraits : detail::SafeVecTraitsImpl<T>
struct VTKM_DEPRECATED(2.1 "VecTraits now safe to use on any type.") VTKM_NEVER_EXPORT SafeVecTraits
: vtkm::VecTraits<T>
{
};
} // namespace internal
/// \brief VecTraits for Pair types
///
/// Although a pair would seem better as a size-2 vector, we treat it as a
/// scalar. This is because a \c Vec is assumed to have the same type for
/// every component, and a pair in general has a different type for each
/// component. Thus we treat a pair as a "scalar" unit.
///
template <typename T, typename U>
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Pair<T, U>>
: public vtkm::internal::VecTraitsBasic<vtkm::Pair<T, U>>
namespace detail
{
struct VTKM_DEPRECATED(2.1,
"VTKM_BASIC_TYPE_VECTOR is no longer necessary because VecTraits implements "
"basic type by default.") VTKM_BASIC_TYPE_VECTOR_is_deprecated
{
};
template <typename T>
struct issue_VTKM_BASIC_TYPE_VECTOR_deprecation_warning;
}
} // namespace vtkm
#define VTKM_BASIC_TYPE_VECTOR(type) \
namespace vtkm \
{ \
template <> \
struct VTKM_NEVER_EXPORT VecTraits<type> : public vtkm::internal::VecTraitsBasic<type> \
{ \
}; \
#define VTKM_BASIC_TYPE_VECTOR(type) \
namespace vtkm \
{ \
namespace detail \
{ \
template <> \
struct issue_VTKM_BASIC_TYPE_VECTOR_deprecation_warning<type> \
: public vtkm::detail::VTKM_BASIC_TYPE_VECTOR_is_deprecated \
{ \
}; \
} \
}
/// Allows you to treat basic types as if they were vectors.
VTKM_BASIC_TYPE_VECTOR(float)
VTKM_BASIC_TYPE_VECTOR(double)
VTKM_BASIC_TYPE_VECTOR(bool)
VTKM_BASIC_TYPE_VECTOR(char)
VTKM_BASIC_TYPE_VECTOR(signed char)
VTKM_BASIC_TYPE_VECTOR(unsigned char)
VTKM_BASIC_TYPE_VECTOR(short)
VTKM_BASIC_TYPE_VECTOR(unsigned short)
VTKM_BASIC_TYPE_VECTOR(int)
VTKM_BASIC_TYPE_VECTOR(unsigned int)
VTKM_BASIC_TYPE_VECTOR(long)
VTKM_BASIC_TYPE_VECTOR(unsigned long)
VTKM_BASIC_TYPE_VECTOR(long long)
VTKM_BASIC_TYPE_VECTOR(unsigned long long)
//#undef VTKM_BASIC_TYPE_VECTOR
#endif //vtk_m_VecTraits_h

@ -33,21 +33,6 @@ namespace cont
namespace detail
{
// Compile-time check to make sure that an `ArrayHandle` passed to `ArrayCopy`
// can be passed to a `UnknownArrayHandle`. This function does nothing
// except provide a compile error that is easier to understand than if you
// let it go and error in `UnknownArrayHandle`. (Huh? I'm not using that.)
template <typename T>
inline void ArrayCopyValueTypeCheck()
{
VTKM_STATIC_ASSERT_MSG(vtkm::HasVecTraits<T>::value,
"An `ArrayHandle` that has a special value type that is not supported "
"by the precompiled version of `ArrayCopy` has been used. If this array "
"must be deep copied, consider using `ArrayCopyDevice`. Look at the "
"compile error for the type assigned to template parameter `T` to "
"see the offending type.");
}
template <typename S>
struct ArrayCopyConcreteSrc;
@ -74,8 +59,6 @@ void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
std::false_type,
std::true_type)
{
detail::ArrayCopyValueTypeCheck<T>();
using DestType = vtkm::cont::ArrayHandle<T, S>;
if (source.CanConvert<DestType>())
{
@ -96,9 +79,6 @@ void ArrayCopyImpl(const vtkm::cont::ArrayHandle<TS, SS>& source,
std::true_type,
std::true_type)
{
ArrayCopyValueTypeCheck<TS>();
ArrayCopyValueTypeCheck<TD>();
detail::ArrayCopyConcreteSrc<SS>{}(source, destination);
}

@ -37,7 +37,7 @@ namespace internal
// is defined rather than where it is resolved. This causes problems when extracting
// components of, say, an ArrayHandleMultiplexer holding an ArrayHandleSOA.
template <typename T, typename S>
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType>
ArrayExtractComponentFallback(const vtkm::cont::ArrayHandle<T, S>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy)
@ -53,7 +53,7 @@ ArrayExtractComponentFallback(const vtkm::cont::ArrayHandle<T, S>& src,
<< vtkm::cont::TypeToString<vtkm::cont::ArrayHandle<T, S>>()
<< " requires an inefficient memory copy.");
using BaseComponentType = typename vtkm::internal::SafeVecTraits<T>::BaseComponentType;
using BaseComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
vtkm::Id numValues = src.GetNumberOfValues();
vtkm::cont::ArrayHandleBasic<BaseComponentType> dest;
dest.Allocate(numValues);
@ -78,10 +78,10 @@ template <typename S>
struct ArrayExtractComponentImpl : ArrayExtractComponentImplInefficient
{
template <typename T>
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
operator()(const vtkm::cont::ArrayHandle<T, S>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy) const
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
const vtkm::cont::ArrayHandle<T, S>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy) const
{
// This is the slow "default" implementation. ArrayHandle implementations should provide
// more efficient overloads where applicable.
@ -93,15 +93,13 @@ template <>
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagStride>
{
template <typename T>
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
operator()(const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy) const
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy) const
{
return this->DoExtract(src,
componentIndex,
allowCopy,
typename vtkm::internal::SafeVecTraits<T>::HasMultipleComponents{});
return this->DoExtract(
src, componentIndex, allowCopy, typename vtkm::VecTraits<T>::HasMultipleComponents{});
}
private:
@ -112,7 +110,7 @@ private:
vtkm::VecTraitsTagSingleComponent) const
{
VTKM_ASSERT(componentIndex == 0);
using VTraits = vtkm::internal::SafeVecTraits<T>;
using VTraits = vtkm::VecTraits<T>;
using TBase = typename VTraits::BaseComponentType;
VTKM_STATIC_ASSERT(VTraits::NUM_COMPONENTS == 1);
@ -135,7 +133,7 @@ private:
vtkm::CopyFlag allowCopy,
vtkm::VecTraitsTagMultipleComponents) const
{
using VTraits = vtkm::internal::SafeVecTraits<VecType>;
using VTraits = vtkm::VecTraits<VecType>;
using T = typename VTraits::ComponentType;
constexpr vtkm::IdComponent N = VTraits::NUM_COMPONENTS;
@ -254,10 +252,10 @@ using ArrayExtractComponentIsInefficient = typename std::is_base_of<
/// `vtkm::cont::internal::ArrayExtractComponentImpl`.
///
template <typename T, typename S>
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
ArrayExtractComponent(const vtkm::cont::ArrayHandle<T, S>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy = vtkm::CopyFlag::On)
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> ArrayExtractComponent(
const vtkm::cont::ArrayHandle<T, S>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy = vtkm::CopyFlag::On)
{
return internal::ArrayExtractComponentImpl<S>{}(src, componentIndex, allowCopy);
}

@ -120,9 +120,6 @@ VTKM_CONT void ArrayGetValues(const vtkm::cont::ArrayHandle<vtkm::Id, SIds>& ids
const vtkm::cont::ArrayHandle<T, SData>& data,
vtkm::cont::ArrayHandle<T, SOut>& output)
{
VTKM_STATIC_ASSERT_MSG(
vtkm::HasVecTraits<T>::value,
"ArrayGetValues can only be used with arrays containing value types with VecTraits defined.");
using DataArrayHandle = vtkm::cont::ArrayHandle<T, SData>;
using InefficientExtract =
vtkm::cont::internal::ArrayExtractComponentIsInefficient<DataArrayHandle>;

@ -752,9 +752,9 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle_Value(
std::ostream& out,
vtkm::VecTraitsTagMultipleComponents)
{
using Traits = vtkm::internal::SafeVecTraits<T>;
using Traits = vtkm::VecTraits<T>;
using ComponentType = typename Traits::ComponentType;
using IsVecOfVec = typename vtkm::internal::SafeVecTraits<ComponentType>::HasMultipleComponents;
using IsVecOfVec = typename vtkm::VecTraits<ComponentType>::HasMultipleComponents;
vtkm::IdComponent numComponents = Traits::GetNumberOfComponents(value);
out << "(";
printSummary_ArrayHandle_Value(Traits::GetComponent(value, 0), out, IsVecOfVec());
@ -774,10 +774,10 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle_Value(
{
out << "{";
printSummary_ArrayHandle_Value(
value.first, out, typename vtkm::internal::SafeVecTraits<T1>::HasMultipleComponents());
value.first, out, typename vtkm::VecTraits<T1>::HasMultipleComponents());
out << ",";
printSummary_ArrayHandle_Value(
value.second, out, typename vtkm::internal::SafeVecTraits<T2>::HasMultipleComponents());
value.second, out, typename vtkm::VecTraits<T2>::HasMultipleComponents());
out << "}";
}
@ -793,7 +793,7 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle(
{
using ArrayType = vtkm::cont::ArrayHandle<T, StorageT>;
using PortalType = typename ArrayType::ReadPortalType;
using IsVec = typename vtkm::internal::SafeVecTraits<T>::HasMultipleComponents;
using IsVec = typename vtkm::VecTraits<T>::HasMultipleComponents;
vtkm::Id sz = array.GetNumberOfValues();

@ -77,27 +77,17 @@ private:
namespace detail
{
template <typename T, typename UseVecTraits = vtkm::HasVecTraits<T>>
struct CanCountImpl;
template <typename T>
struct CanCountImpl<T, std::false_type>
{
using TTraits = vtkm::TypeTraits<T>;
static constexpr bool IsNumeric =
!std::is_same<typename TTraits::NumericTag, vtkm::TypeTraitsUnknownTag>::value;
static constexpr bool value = IsNumeric;
};
template <typename T>
struct CanCountImpl<T, std::true_type>
struct CanCountImpl
{
using VTraits = vtkm::VecTraits<T>;
using BaseType = typename VTraits::BaseComponentType;
using TTraits = vtkm::TypeTraits<BaseType>;
static constexpr bool IsNumeric =
!std::is_same<typename TTraits::NumericTag, vtkm::TypeTraitsUnknownTag>::value;
static constexpr bool IsBool = std::is_same<BaseType, bool>::value;
static constexpr bool value = CanCountImpl<BaseType, std::false_type>::value && !IsBool;
static constexpr bool value = IsNumeric && !IsBool;
};
} // namespace detail

@ -87,7 +87,7 @@ public:
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator=(const T& src)
{
this->DoCopy(src);
@ -104,7 +104,7 @@ public:
return result;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator+=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -115,7 +115,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator-=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -126,7 +126,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator*=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -137,7 +137,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator/=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -148,7 +148,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator%=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -159,7 +159,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator&=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -170,7 +170,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator|=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -181,7 +181,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator^=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -192,7 +192,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator>>=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;
@ -203,7 +203,7 @@ public:
}
return *this;
}
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
template <typename T>
VTKM_EXEC_CONT RecombineVec& operator<<=(const T& src)
{
using VTraits = vtkm::VecTraits<T>;

@ -141,7 +141,7 @@ class Storage<vtkm::VecFromPortal<ComponentsPortal>, vtkm::cont::StorageTagRunti
vtkm::cont::internal::Storage<ComponentType, vtkm::cont::StorageTagBasic>;
VTKM_STATIC_ASSERT_MSG(
vtkm::internal::SafeVecTraits<ComponentType>::NUM_COMPONENTS == 1,
vtkm::VecTraits<ComponentType>::NUM_COMPONENTS == 1,
"ArrayHandleRuntimeVec only supports scalars grouped into a single Vec. Nested Vecs can "
"still be used with ArrayHandleRuntimeVec. The values are treated as flattened (like "
"with VecFlat).");

@ -44,7 +44,6 @@ public:
private:
using ComponentType = typename ComponentPortalType::ValueType;
VTKM_STATIC_ASSERT(vtkm::HasVecTraits<ValueType>::value);
using VTraits = vtkm::VecTraits<ValueType>;
VTKM_STATIC_ASSERT((std::is_same<typename VTraits::ComponentType, ComponentType>::value));
static constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;

@ -82,11 +82,9 @@ inline auto UnknownAHNumberOfComponentsImpl(void* mem)
// of a use case for the storage to report the number of components for a static data type.
// If that happens, this implementation will need to be modified.
template <typename T, typename S>
inline auto UnknownAHNumberOfComponentsImpl(void*)
-> decltype(vtkm::internal::SafeVecTraits<T>::NUM_COMPONENTS)
inline auto UnknownAHNumberOfComponentsImpl(void*) -> decltype(vtkm::VecTraits<T>::NUM_COMPONENTS)
{
static constexpr vtkm::IdComponent numComponents =
vtkm::internal::SafeVecTraits<T>::NUM_COMPONENTS;
static constexpr vtkm::IdComponent numComponents = vtkm::VecTraits<T>::NUM_COMPONENTS;
return numComponents;
}
@ -117,7 +115,7 @@ inline auto UnknownAHNumberOfComponentsFlatImpl(void* mem)
// static. If a future `ArrayHandle` type violates this, this code will have to become
// more complex.
return (vtkm::cont::internal::Storage<T, S>::GetNumberOfComponents(arrayHandle->GetBuffers()) *
vtkm::VecFlat<typename vtkm::internal::SafeVecTraits<T>::ComponentType>::NUM_COMPONENTS);
vtkm::VecFlat<typename vtkm::VecTraits<T>::ComponentType>::NUM_COMPONENTS);
}
// Uses SFINAE to use the number of compnents in VecTraits.
@ -364,14 +362,13 @@ std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTag
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic()
{
return UnknownAHNewInstanceBasic<T>(typename vtkm::internal::SafeVecTraits<T>::IsSizeStatic{});
return UnknownAHNewInstanceBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
}
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeStatic)
{
using FloatT = typename vtkm::internal::SafeVecTraits<T>::template ReplaceBaseComponentType<
vtkm::FloatDefault>;
using FloatT = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::FloatDefault>;
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<FloatT>{});
}
template <typename T>
@ -383,8 +380,7 @@ std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTrai
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic()
{
return UnknownAHNewInstanceFloatBasic<T>(
typename vtkm::internal::SafeVecTraits<T>::IsSizeStatic{});
return UnknownAHNewInstanceFloatBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
}
template <typename T, typename S>
@ -393,7 +389,7 @@ inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S
, ValueType(typeid(T))
, StorageType(typeid(S))
, BaseComponentType(
UnknownAHComponentInfo::Make<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>())
UnknownAHComponentInfo::Make<typename vtkm::VecTraits<T>::BaseComponentType>())
, DeleteFunction(detail::UnknownAHDelete<T, S>)
, Buffers(detail::UnknownAHBuffers<T, S>)
, NewInstance(detail::UnknownAHNewInstance<T, S>)
@ -1031,8 +1027,8 @@ namespace detail
{
template <typename T,
vtkm::IdComponent = vtkm::internal::SafeVecTraits<
typename vtkm::internal::UnrollVec<T>::ComponentType>::NUM_COMPONENTS>
vtkm::IdComponent =
vtkm::VecTraits<typename vtkm::internal::UnrollVec<T>::ComponentType>::NUM_COMPONENTS>
struct UnknownArrayHandleRuntimeVecAsBasic
{
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle*,

@ -36,7 +36,6 @@ struct MapPermutationWorklet : vtkm::worklet::WorkletMapField
InputPortalType inputPortal,
OutputType& output) const
{
VTKM_STATIC_ASSERT(vtkm::HasVecTraits<OutputType>::value);
if ((permutationIndex >= 0) && (permutationIndex < inputPortal.GetNumberOfValues()))
{
output = inputPortal.Get(permutationIndex);

@ -76,8 +76,8 @@ struct PassThrough : vtkm::worklet::WorkletMapField
OutValue& outValue,
vtkm::IdComponent& outIndex) const
{
using VTraitsIn = vtkm::internal::SafeVecTraits<InValue>;
using VTraitsOut = vtkm::internal::SafeVecTraits<OutValue>;
using VTraitsIn = vtkm::VecTraits<InValue>;
using VTraitsOut = vtkm::VecTraits<OutValue>;
VTraitsOut::SetComponent(outValue, outIndex, VTraitsIn::GetComponent(inValue, inIndex));
inIndex++;
outIndex++;

@ -19,39 +19,6 @@ namespace vtkm
namespace internal
{
namespace detail
{
// TODO: VecTraits should just always be supported. See #589.
template <typename Vec, typename = typename std::enable_if<vtkm::HasVecTraits<Vec>::value>::type>
VTKM_EXEC_CONT inline vtkm::IdComponent SafeGetNumberOfComponents(const Vec& vec)
{
return vtkm::VecTraits<Vec>::GetNumberOfComponents(vec);
}
VTKM_EXEC_CONT inline vtkm::IdComponent SafeGetNumberOfComponents(...)
{
return 1;
}
template <typename Vec, typename = typename std::enable_if<vtkm::HasVecTraits<Vec>::value>::type>
VTKM_EXEC_CONT inline typename vtkm::VecTraits<Vec>::ComponentType SafeGetComponent(
const Vec& vec,
vtkm::IdComponent index)
{
return vtkm::VecTraits<Vec>::GetComponent(vec, index);
}
template <typename T, typename = typename std::enable_if<!vtkm::HasVecTraits<T>::value>::type>
VTKM_EXEC_CONT inline T SafeGetComponent(const T& value, vtkm::IdComponent index)
{
VTKM_ASSERT(index == 0);
return value;
}
} // namespace detail
/// \brief A value class for returning setable values of an ArrayPortal
///
/// \c ArrayPortal classes have a pair of \c Get and \c Set methods that
@ -350,12 +317,12 @@ struct ArrayPortalValueReference
// cannot write components one at a time.
VTKM_EXEC_CONT vtkm::IdComponent GetNumberOfComponents() const
{
return detail::SafeGetNumberOfComponents(static_cast<ValueType>(*this));
return vtkm::VecTraits<ValueType>::GetNumberOfComponents(this->Get());
}
VTKM_EXEC_CONT auto operator[](vtkm::IdComponent index) const
-> decltype(detail::SafeGetComponent(std::declval<ValueType>(), index))
VTKM_EXEC_CONT
typename vtkm::VecTraits<ValueType>::ComponentType operator[](vtkm::IdComponent index) const
{
return detail::SafeGetComponent(static_cast<ValueType>(*this), index);
return vtkm::VecTraits<ValueType>::GetComponent(this->Get(), index);
}
private:

@ -242,11 +242,9 @@ inline void SelectTypeAndCall(DataType dtype,
assert(false);
}
}
}
}
} // namespace vtkm::io::internal
VTKM_BASIC_TYPE_VECTOR(vtkm::io::internal::ColorChannel8)
VTKM_BASIC_TYPE_VECTOR(vtkm::io::internal::DummyBitType)
#endif // vtk_m_io_internal_VTKDataSetTypes_h

@ -624,12 +624,8 @@ namespace detail
template <typename T1, typename T2>
struct TestEqualImpl
{
template <typename Dimensionality1, typename Dimensionality2>
VTKM_EXEC_CONT bool DoIt(T1 vector1,
T2 vector2,
vtkm::Float64 tolerance,
Dimensionality1,
Dimensionality2) const
template <typename IsBase1, typename IsBase2>
VTKM_EXEC_CONT bool DoIt(T1 vector1, T2 vector2, vtkm::Float64 tolerance, IsBase1, IsBase2) const
{
using Traits1 = vtkm::VecTraits<T1>;
using Traits2 = vtkm::VecTraits<T2>;
@ -658,8 +654,8 @@ struct TestEqualImpl
VTKM_EXEC_CONT bool DoIt(T1 scalar1,
T2 scalar2,
vtkm::Float64 tolerance,
vtkm::TypeTraitsScalarTag,
vtkm::TypeTraitsScalarTag) const
std::true_type,
std::true_type) const
{
// Do all comparisons using 64-bit floats.
return test_equal(
@ -668,11 +664,13 @@ struct TestEqualImpl
VTKM_EXEC_CONT bool operator()(T1 value1, T2 value2, vtkm::Float64 tolerance) const
{
using Base1 = typename vtkm::VecTraits<T1>::BaseComponentType;
using Base2 = typename vtkm::VecTraits<T2>::BaseComponentType;
return this->DoIt(value1,
value2,
tolerance,
typename vtkm::TypeTraits<T1>::DimensionalityTag(),
typename vtkm::TypeTraits<T2>::DimensionalityTag());
typename std::is_same<T1, Base1>::type{},
typename std::is_same<T2, Base2>::type{});
}
};

@ -17,12 +17,18 @@ namespace
static constexpr vtkm::Id MAX_VECTOR_SIZE = 5;
static constexpr vtkm::Id VecInit[MAX_VECTOR_SIZE] = { 42, 54, 67, 12, 78 };
void ExpectTrueType(std::true_type) {}
void ExpectFalseType(std::false_type) {}
struct TypeWithoutVecTraits
{
vtkm::Id Value = -1;
TypeWithoutVecTraits() = default;
TypeWithoutVecTraits(vtkm::Id value)
: Value(value)
{
}
operator vtkm::Id() const { return this->Value; }
};
struct TestVecTypeFunctor
@ -30,9 +36,6 @@ struct TestVecTypeFunctor
template <typename T>
void operator()(const T&) const
{
// Make sure that VecTraits actually exists
ExpectTrueType(vtkm::HasVecTraits<T>());
using Traits = vtkm::VecTraits<T>;
using ComponentType = typename Traits::ComponentType;
VTKM_TEST_ASSERT(Traits::NUM_COMPONENTS <= MAX_VECTOR_SIZE,
@ -59,8 +62,8 @@ void TestVecTraits()
vtkm::testing::Testing::TryTypes(test);
std::cout << "vtkm::Vec<vtkm::FloatDefault, 5>" << std::endl;
test(vtkm::Vec<vtkm::FloatDefault, 5>());
ExpectFalseType(vtkm::HasVecTraits<TypeWithoutVecTraits>());
std::cout << "TypeWithoutVecTraits" << std::endl;
test(TypeWithoutVecTraits{});
vtkm::testing::TestVecComponentsTag<vtkm::Id3>();
vtkm::testing::TestVecComponentsTag<vtkm::Vec3f>();
@ -69,6 +72,7 @@ void TestVecTraits()
vtkm::testing::TestVecComponentsTag<vtkm::VecCConst<vtkm::Id>>();
vtkm::testing::TestScalarComponentsTag<vtkm::Id>();
vtkm::testing::TestScalarComponentsTag<vtkm::FloatDefault>();
vtkm::testing::TestScalarComponentsTag<TypeWithoutVecTraits>();
}
} // anonymous namespace

@ -47,6 +47,12 @@ inline void CompareDimensionalityTags(vtkm::TypeTraitsVectorTag,
{
// If we are here, everything is fine.
}
inline void CompareDimensionalityTags(vtkm::TypeTraitsUnknownTag, vtkm::VecTraitsTagSingleComponent)
{
// If we are here, type traits are probably not defined (and default to unknown). In this case,
// we expect VecTraits to have the default implementation, in which case it is treated as a
// single component.
}
template <vtkm::IdComponent NUM_COMPONENTS, typename T>
inline void CheckIsStatic(const T&, vtkm::VecTraitsTagSizeStatic)
@ -73,6 +79,12 @@ struct VecIsWritable<vtkm::VecCConst<ComponentType>>
using type = std::false_type;
};
template <typename ComponentType>
struct VecIsWritable<vtkm::VecCConst<ComponentType>*>
{
using type = std::false_type;
};
// Part of TestVecTypeImpl that writes to the Vec type
template <vtkm::IdComponent NUM_COMPONENTS, typename T, typename VecCopyType>
static void TestVecTypeWritableImpl(const T& inVector,
@ -150,8 +162,9 @@ static void TestVecTypeImpl(const typename std::remove_const<T>::type& inVector,
}
// This will fail to compile if the tags are wrong.
detail::CompareDimensionalityTags(typename vtkm::TypeTraits<T>::DimensionalityTag(),
typename vtkm::VecTraits<T>::HasMultipleComponents());
detail::CompareDimensionalityTags(
typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag(),
typename vtkm::VecTraits<T>::HasMultipleComponents());
TestVecTypeWritableImpl<NUM_COMPONENTS, NonConstT>(
inVector, vectorCopy, outVector, typename VecIsWritable<NonConstT>::type());
@ -159,7 +172,9 @@ static void TestVecTypeImpl(const typename std::remove_const<T>::type& inVector,
// Compiler checks for base component types
using BaseComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
VTKM_STATIC_ASSERT((std::is_same<typename vtkm::TypeTraits<BaseComponentType>::DimensionalityTag,
vtkm::TypeTraitsScalarTag>::value));
vtkm::TypeTraitsScalarTag>::value) ||
(std::is_same<typename vtkm::TypeTraits<BaseComponentType>::DimensionalityTag,
vtkm::TypeTraitsUnknownTag>::value));
VTKM_STATIC_ASSERT((std::is_same<typename vtkm::VecTraits<ComponentType>::BaseComponentType,
BaseComponentType>::value));
@ -167,12 +182,12 @@ static void TestVecTypeImpl(const typename std::remove_const<T>::type& inVector,
using ReplaceWithVecComponent =
typename vtkm::VecTraits<T>::template ReplaceComponentType<vtkm::Vec<char, 2>>;
VTKM_STATIC_ASSERT(
(std::is_same<typename vtkm::TypeTraits<T>::DimensionalityTag,
(std::is_same<typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag,
vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::ComponentType,
vtkm::Vec<char, 2>>::value) ||
(std::is_same<typename vtkm::TypeTraits<T>::DimensionalityTag,
vtkm::TypeTraitsScalarTag>::value &&
(!std::is_same<typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag,
vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::ComponentType, char>::value));
VTKM_STATIC_ASSERT(
(std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::BaseComponentType,
@ -180,12 +195,12 @@ static void TestVecTypeImpl(const typename std::remove_const<T>::type& inVector,
using ReplaceBaseComponent =
typename vtkm::VecTraits<ReplaceWithVecComponent>::template ReplaceBaseComponentType<short>;
VTKM_STATIC_ASSERT(
(std::is_same<typename vtkm::TypeTraits<T>::DimensionalityTag,
(std::is_same<typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag,
vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::ComponentType,
vtkm::Vec<short, 2>>::value) ||
(std::is_same<typename vtkm::TypeTraits<T>::DimensionalityTag,
vtkm::TypeTraitsScalarTag>::value &&
(!std::is_same<typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag,
vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::ComponentType, short>::value));
VTKM_STATIC_ASSERT((
std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::BaseComponentType, short>::value));
@ -227,6 +242,13 @@ static void TestVecType(const T& inVector, T& outVector)
{
detail::TestVecTypeImpl<NUM_COMPONENTS, T>(inVector, outVector);
detail::TestVecTypeImpl<NUM_COMPONENTS, const T>(inVector, outVector);
// The local pointer variables are for some weirdness about `TestVecTypeImpl` taking references
// of its argument type.
T* inPointer = const_cast<T*>(&inVector);
T* outPointer = &outVector;
detail::TestVecTypeImpl<NUM_COMPONENTS, T*>(inPointer, outPointer);
VTKM_STATIC_ASSERT_MSG((std::is_base_of<vtkm::VecTraits<T*>, vtkm::VecTraits<const T*>>::value),
"Constant pointer should have same implementation as pointer.");
}
/// Checks to make sure that the HasMultipleComponents tag is actually for a