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. /// \brief A tag to determine whether the type has multiple components.
/// ///
/// This tag is either TypeTraitsScalarTag or TypeTraitsVectorTag. Scalars can /// 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; using DimensionalityTag = vtkm::TypeTraitsUnknownTag;
VTKM_EXEC_CONT static T ZeroInitialization() { return T(); } VTKM_EXEC_CONT static T ZeroInitialization() { return T(); }

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

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

@ -10,6 +10,8 @@
#ifndef vtk_m_VecTraits_h #ifndef vtk_m_VecTraits_h
#define vtk_m_VecTraits_h #define vtk_m_VecTraits_h
#include <vtkm/Deprecated.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/Types.h> #include <vtkm/Types.h>
namespace vtkm namespace vtkm
@ -42,64 +44,55 @@ struct VecTraitsTagSizeVariable
{ {
}; };
namespace internal /// \brief Traits that can be queried to treat any type as a `Vec`.
{
// 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.
/// ///
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 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. /// \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. /// 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. /// \brief Base component type in the vector.
/// ///
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it /// 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). /// 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. /// \brief Number of components in the vector.
/// ///
/// This is only defined for vectors of a static size. /// 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. /// 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). /// \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 /// This tag can be useful for creating specialized functions when a vector
/// is really just a scalar. /// is really just a scalar.
/// ///
using HasMultipleComponents = using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent;
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS, ComponentType>::Type;
/// \brief A tag specifying whether the size of this vector is known at compile time. /// \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. /// Returns the value in a given component of the vector.
/// ///
VTKM_EXEC_CONT static const ComponentType& GetComponent( VTKM_EXEC_CONT static const ComponentType& GetComponent(const T& vector,
const typename std::remove_const<VecType>::type& vector, vtkm::IdComponent vtkmNotUsed(component))
vtkm::IdComponent component); {
VTKM_EXEC_CONT static ComponentType& GetComponent( return vector;
typename std::remove_const<VecType>::type& vector, }
vtkm::IdComponent component); VTKM_EXEC_CONT static ComponentType& GetComponent(T& vector,
vtkm::IdComponent vtkmNotUsed(component))
{
return vector;
}
/// Changes the value in a given component of the vector. /// Changes the value in a given component of the vector.
/// ///
VTKM_EXEC_CONT static void SetComponent(VecType& vector, VTKM_EXEC_CONT static void SetComponent(T& vector,
vtkm::IdComponent component, vtkm::IdComponent vtkmNotUsed(component),
ComponentType value); ComponentType value)
{
vector = value;
}
/// \brief Get a vector of the same type but with a different component. /// \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, /// 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>. /// `vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2>` is `vtkm::Vec<T2, N>`.
/// This replacement is not recursive. So @code VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> @endcode /// This replacement is not recursive. So `VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>`
/// is vtkm::Vec<T2, N>. /// is `vtkm::Vec<T2, N>`.
/// ///
template <typename NewComponentType> 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. /// \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 /// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example, /// 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> template <typename NewComponentType>
using ReplaceBaseComponentType = VecTemplate< using ReplaceBaseComponentType = NewComponentType;
typename VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
N>;
/// Copies the components in the given vector into a given Vec object. /// Copies the components in the given vector into a given Vec object.
/// ///
template <vktm::IdComponent destSize> template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest); VTKM_EXEC_CONT static void CopyInto(const T& src, vtkm::Vec<ComponentType, destSize>& dest)
#endif // VTKM_DOXYGEN_ONLY {
dest[0] = src;
}
}; };
namespace detail
{
template <typename T> template <typename T>
struct HasVecTraitsImpl using HasVecTraits VTKM_DEPRECATED(2.1, "All types now have VecTraits defined.") = std::true_type;
{
template <typename A, typename S = typename vtkm::VecTraits<A>::ComponentType>
static std::true_type Test(A*);
static std::false_type Test(...); // These partial specializations allow VecTraits to work with const and reference qualifiers.
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.
//
template <typename T> template <typename T>
struct VTKM_NEVER_EXPORT VecTraits<const T> : VecTraits<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) #if defined(VTKM_GCC) && (__GNUC__ <= 5)
namespace detail namespace detail
@ -201,13 +226,29 @@ template <typename T, vtkm::IdComponent Size, typename NewT>
struct VecReplaceBaseComponentTypeGCC4or5 struct VecReplaceBaseComponentTypeGCC4or5
{ {
using type = using type =
vtkm::Vec<typename vtkm::internal::SafeVecTraits<T>::template ReplaceBaseComponentType<NewT>, vtkm::Vec<typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<NewT>, Size>;
Size>;
}; };
} // namespace detail } // namespace detail
#endif // GCC Version 4.8 #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> template <typename T, vtkm::IdComponent Size>
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, 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 /// 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). /// returns the base scalar type at the end of the composition (T in this example).
/// ///
using BaseComponentType = using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
typename vtkm::internal::SafeVecTraits<ComponentType>::BaseComponentType;
/// Number of components in the vector. /// 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; typename detail::VecReplaceBaseComponentTypeGCC4or5<T, Size, NewComponentType>::type;
#else // !GCC <= 5 #else // !GCC <= 5
template <typename NewComponentType> template <typename NewComponentType>
using ReplaceBaseComponentType = using ReplaceBaseComponentType = vtkm::Vec<
vtkm::Vec<typename vtkm::internal::SafeVecTraits< typename vtkm::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
ComponentType>::template ReplaceBaseComponentType<NewComponentType>, Size>;
Size>;
#endif #endif
///@} ///@}
@ -509,7 +548,8 @@ namespace internal
/// Used for overriding VecTraits for basic scalar types. /// Used for overriding VecTraits for basic scalar types.
/// ///
template <typename ScalarType> 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 ComponentType = ScalarType;
using BaseComponentType = 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> template <typename T>
struct VTKM_NEVER_EXPORT SafeVecTraitsImpl<T, std::true_type> : vtkm::VecTraits<T> struct VTKM_DEPRECATED(2.1 "VecTraits now safe to use on any type.") VTKM_NEVER_EXPORT SafeVecTraits
{ : 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>
{ {
}; };
} // namespace internal } // namespace internal
/// \brief VecTraits for Pair types namespace detail
/// {
/// 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 struct VTKM_DEPRECATED(2.1,
/// every component, and a pair in general has a different type for each "VTKM_BASIC_TYPE_VECTOR is no longer necessary because VecTraits implements "
/// component. Thus we treat a pair as a "scalar" unit. "basic type by default.") VTKM_BASIC_TYPE_VECTOR_is_deprecated
///
template <typename T, typename U>
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Pair<T, U>>
: public vtkm::internal::VecTraitsBasic<vtkm::Pair<T, U>>
{ {
}; };
template <typename T>
struct issue_VTKM_BASIC_TYPE_VECTOR_deprecation_warning;
}
} // namespace vtkm } // namespace vtkm
#define VTKM_BASIC_TYPE_VECTOR(type) \ #define VTKM_BASIC_TYPE_VECTOR(type) \
namespace vtkm \ namespace vtkm \
{ \ { \
template <> \ namespace detail \
struct VTKM_NEVER_EXPORT VecTraits<type> : public vtkm::internal::VecTraitsBasic<type> \ { \
{ \ 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 #endif //vtk_m_VecTraits_h

@ -33,21 +33,6 @@ namespace cont
namespace detail 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> template <typename S>
struct ArrayCopyConcreteSrc; struct ArrayCopyConcreteSrc;
@ -74,8 +59,6 @@ void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
std::false_type, std::false_type,
std::true_type) std::true_type)
{ {
detail::ArrayCopyValueTypeCheck<T>();
using DestType = vtkm::cont::ArrayHandle<T, S>; using DestType = vtkm::cont::ArrayHandle<T, S>;
if (source.CanConvert<DestType>()) if (source.CanConvert<DestType>())
{ {
@ -96,9 +79,6 @@ void ArrayCopyImpl(const vtkm::cont::ArrayHandle<TS, SS>& source,
std::true_type, std::true_type,
std::true_type) std::true_type)
{ {
ArrayCopyValueTypeCheck<TS>();
ArrayCopyValueTypeCheck<TD>();
detail::ArrayCopyConcreteSrc<SS>{}(source, destination); detail::ArrayCopyConcreteSrc<SS>{}(source, destination);
} }

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

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

@ -77,27 +77,17 @@ private:
namespace detail namespace detail
{ {
template <typename T, typename UseVecTraits = vtkm::HasVecTraits<T>>
struct CanCountImpl;
template <typename T> template <typename T>
struct CanCountImpl<T, std::false_type> struct CanCountImpl
{
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>
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
using BaseType = typename VTraits::BaseComponentType; 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 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 } // namespace detail

@ -87,7 +87,7 @@ public:
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator=(const T& src)
{ {
this->DoCopy(src); this->DoCopy(src);
@ -104,7 +104,7 @@ public:
return result; 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) VTKM_EXEC_CONT RecombineVec& operator+=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -115,7 +115,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator-=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -126,7 +126,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator*=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -137,7 +137,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator/=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -148,7 +148,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator%=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -159,7 +159,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator&=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -170,7 +170,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator|=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -181,7 +181,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator^=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -192,7 +192,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator>>=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; using VTraits = vtkm::VecTraits<T>;
@ -203,7 +203,7 @@ public:
} }
return *this; 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) VTKM_EXEC_CONT RecombineVec& operator<<=(const T& src)
{ {
using VTraits = vtkm::VecTraits<T>; 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::cont::internal::Storage<ComponentType, vtkm::cont::StorageTagBasic>;
VTKM_STATIC_ASSERT_MSG( 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 " "ArrayHandleRuntimeVec only supports scalars grouped into a single Vec. Nested Vecs can "
"still be used with ArrayHandleRuntimeVec. The values are treated as flattened (like " "still be used with ArrayHandleRuntimeVec. The values are treated as flattened (like "
"with VecFlat)."); "with VecFlat).");

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

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

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

@ -19,39 +19,6 @@ namespace vtkm
namespace internal 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 /// \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 /// \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. // cannot write components one at a time.
VTKM_EXEC_CONT vtkm::IdComponent GetNumberOfComponents() const 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 VTKM_EXEC_CONT
-> decltype(detail::SafeGetComponent(std::declval<ValueType>(), index)) 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: private:

@ -242,11 +242,9 @@ inline void SelectTypeAndCall(DataType dtype,
assert(false); assert(false);
} }
} }
} }
} }
} // namespace vtkm::io::internal } // 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 #endif // vtk_m_io_internal_VTKDataSetTypes_h

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

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

@ -47,6 +47,12 @@ inline void CompareDimensionalityTags(vtkm::TypeTraitsVectorTag,
{ {
// If we are here, everything is fine. // 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> template <vtkm::IdComponent NUM_COMPONENTS, typename T>
inline void CheckIsStatic(const T&, vtkm::VecTraitsTagSizeStatic) inline void CheckIsStatic(const T&, vtkm::VecTraitsTagSizeStatic)
@ -73,6 +79,12 @@ struct VecIsWritable<vtkm::VecCConst<ComponentType>>
using type = std::false_type; 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 // Part of TestVecTypeImpl that writes to the Vec type
template <vtkm::IdComponent NUM_COMPONENTS, typename T, typename VecCopyType> template <vtkm::IdComponent NUM_COMPONENTS, typename T, typename VecCopyType>
static void TestVecTypeWritableImpl(const T& inVector, 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. // This will fail to compile if the tags are wrong.
detail::CompareDimensionalityTags(typename vtkm::TypeTraits<T>::DimensionalityTag(), detail::CompareDimensionalityTags(
typename vtkm::VecTraits<T>::HasMultipleComponents()); typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag(),
typename vtkm::VecTraits<T>::HasMultipleComponents());
TestVecTypeWritableImpl<NUM_COMPONENTS, NonConstT>( TestVecTypeWritableImpl<NUM_COMPONENTS, NonConstT>(
inVector, vectorCopy, outVector, typename VecIsWritable<NonConstT>::type()); 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 // Compiler checks for base component types
using BaseComponentType = typename vtkm::VecTraits<T>::BaseComponentType; using BaseComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
VTKM_STATIC_ASSERT((std::is_same<typename vtkm::TypeTraits<BaseComponentType>::DimensionalityTag, 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, VTKM_STATIC_ASSERT((std::is_same<typename vtkm::VecTraits<ComponentType>::BaseComponentType,
BaseComponentType>::value)); BaseComponentType>::value));
@ -167,12 +182,12 @@ static void TestVecTypeImpl(const typename std::remove_const<T>::type& inVector,
using ReplaceWithVecComponent = using ReplaceWithVecComponent =
typename vtkm::VecTraits<T>::template ReplaceComponentType<vtkm::Vec<char, 2>>; typename vtkm::VecTraits<T>::template ReplaceComponentType<vtkm::Vec<char, 2>>;
VTKM_STATIC_ASSERT( 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 && vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::ComponentType, std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::ComponentType,
vtkm::Vec<char, 2>>::value) || vtkm::Vec<char, 2>>::value) ||
(std::is_same<typename vtkm::TypeTraits<T>::DimensionalityTag, (!std::is_same<typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag,
vtkm::TypeTraitsScalarTag>::value && vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::ComponentType, char>::value)); std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::ComponentType, char>::value));
VTKM_STATIC_ASSERT( VTKM_STATIC_ASSERT(
(std::is_same<typename vtkm::VecTraits<ReplaceWithVecComponent>::BaseComponentType, (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 = using ReplaceBaseComponent =
typename vtkm::VecTraits<ReplaceWithVecComponent>::template ReplaceBaseComponentType<short>; typename vtkm::VecTraits<ReplaceWithVecComponent>::template ReplaceBaseComponentType<short>;
VTKM_STATIC_ASSERT( 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 && vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::ComponentType, std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::ComponentType,
vtkm::Vec<short, 2>>::value) || vtkm::Vec<short, 2>>::value) ||
(std::is_same<typename vtkm::TypeTraits<T>::DimensionalityTag, (!std::is_same<typename vtkm::TypeTraits<std::remove_pointer_t<T>>::DimensionalityTag,
vtkm::TypeTraitsScalarTag>::value && vtkm::TypeTraitsVectorTag>::value &&
std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::ComponentType, short>::value)); std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::ComponentType, short>::value));
VTKM_STATIC_ASSERT(( VTKM_STATIC_ASSERT((
std::is_same<typename vtkm::VecTraits<ReplaceBaseComponent>::BaseComponentType, short>::value)); 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, T>(inVector, outVector);
detail::TestVecTypeImpl<NUM_COMPONENTS, const 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 /// Checks to make sure that the HasMultipleComponents tag is actually for a