Add more safety to VecTraits

You can often get compile errors when trying to get `Vec` attributes
from types that do not define `VecTraits`. This is of particular problem
when you create an object like `Vec` with a component that does not
define `VecTraits`. Make using these types safer by internally using
`SafeVecTraits`, which will gracefully handle types that do not have
`VecTraits`.
This commit is contained in:
Kenneth Moreland 2023-02-09 15:27:09 -07:00
parent da731005b3
commit a7679c9e99
3 changed files with 32 additions and 22 deletions

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

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

@ -45,16 +45,20 @@ struct VecTraitsTagSizeVariable
namespace internal
{
template <vtkm::IdComponent numComponents>
// Forward declaration
template <typename T>
struct SafeVecTraits;
template <vtkm::IdComponent numComponents, typename ComponentType>
struct VecTraitsMultipleComponentChooser
{
using Type = vtkm::VecTraitsTagMultipleComponents;
};
template <>
struct VecTraitsMultipleComponentChooser<1>
template <typename ComponentType>
struct VecTraitsMultipleComponentChooser<1, ComponentType>
{
using Type = vtkm::VecTraitsTagSingleComponent;
using Type = typename vtkm::internal::SafeVecTraits<ComponentType>::HasMultipleComponents;
};
} // namespace internal
@ -95,7 +99,7 @@ struct VTKM_NEVER_EXPORT VecTraits
/// is really just a scalar.
///
using HasMultipleComponents =
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS>::Type;
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS, ComponentType>::Type;
/// \brief A tag specifying whether the size of this vector is known at compile time.
///
@ -197,7 +201,8 @@ template <typename T, vtkm::IdComponent Size, typename NewT>
struct VecReplaceBaseComponentTypeGCC4or5
{
using type =
vtkm::Vec<typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<NewT>, Size>;
vtkm::Vec<typename vtkm::internal::SafeVecTraits<T>::template ReplaceBaseComponentType<NewT>,
Size>;
};
} // namespace detail
@ -219,7 +224,8 @@ 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::VecTraits<ComponentType>::BaseComponentType;
using BaseComponentType =
typename vtkm::internal::SafeVecTraits<ComponentType>::BaseComponentType;
/// Number of components in the vector.
///
@ -235,7 +241,7 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
/// when a vector is really just a scalar.
///
using HasMultipleComponents =
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS>::Type;
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS, ComponentType>::Type;
/// A tag specifying whether the size of this vector is known at compile
/// time. If set to \c VecTraitsTagSizeStatic, then \c NUM_COMPONENTS is set.
@ -298,9 +304,10 @@ 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::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
Size>;
using ReplaceBaseComponentType =
vtkm::Vec<typename vtkm::internal::SafeVecTraits<
ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
Size>;
#endif
///@}