From a7679c9e99072bb4aa312ed6c56d6dd161c4020a Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Thu, 9 Feb 2023 15:27:09 -0700 Subject: [PATCH] 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`. --- vtkm/VecFlat.h | 22 ++++++++++++---------- vtkm/VecFromPortal.h | 3 ++- vtkm/VecTraits.h | 29 ++++++++++++++++++----------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/vtkm/VecFlat.h b/vtkm/VecFlat.h index 01d2b5028..476241881 100644 --- a/vtkm/VecFlat.h +++ b/vtkm/VecFlat.h @@ -22,18 +22,20 @@ namespace internal { template ::HasMultipleComponents> + typename MultipleComponents = + typename vtkm::internal::SafeVecTraits::HasMultipleComponents> struct TotalNumComponents; template struct TotalNumComponents { VTKM_STATIC_ASSERT_MSG( - (std::is_same::IsSizeStatic, vtkm::VecTraitsTagSizeStatic>::value), + (std::is_same::IsSizeStatic, + vtkm::VecTraitsTagSizeStatic>::value), "vtkm::VecFlat can only be used with Vec types with a static number of components."); - using ComponentType = typename vtkm::VecTraits::ComponentType; + using ComponentType = typename vtkm::internal::SafeVecTraits::ComponentType; static constexpr vtkm::IdComponent value = - vtkm::VecTraits::NUM_COMPONENTS * TotalNumComponents::value; + vtkm::internal::SafeVecTraits::NUM_COMPONENTS * TotalNumComponents::value; }; template @@ -43,7 +45,7 @@ struct TotalNumComponents }; template -using FlattenVec = vtkm::Vec::BaseComponentType, +using FlattenVec = vtkm::Vec::BaseComponentType, vtkm::internal::TotalNumComponents::value>; template @@ -62,10 +64,10 @@ VTKM_EXEC_CONT T GetFlatVecComponentImpl(const T& component, } template -VTKM_EXEC_CONT typename vtkm::VecTraits::BaseComponentType +VTKM_EXEC_CONT typename vtkm::internal::SafeVecTraits::BaseComponentType GetFlatVecComponentImpl(const T& vec, vtkm::IdComponent index, std::false_type vtkmNotUsed(isBase)) { - using Traits = vtkm::VecTraits; + using Traits = vtkm::internal::SafeVecTraits; 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 -VTKM_EXEC_CONT typename vtkm::VecTraits::BaseComponentType GetFlatVecComponent( +VTKM_EXEC_CONT typename vtkm::internal::SafeVecTraits::BaseComponentType GetFlatVecComponent( const T& vec, vtkm::IdComponent index) { @@ -112,7 +114,7 @@ VTKM_EXEC_CONT void CopyVecNestedToFlatImpl(const NestedVecType& nestedVec, vtkm::Vec& flatVec, vtkm::IdComponent flatOffset) { - using Traits = vtkm::VecTraits; + using Traits = vtkm::internal::SafeVecTraits; using ComponentType = typename Traits::ComponentType; constexpr vtkm::IdComponent subSize = TotalNumComponents::value; @@ -174,7 +176,7 @@ VTKM_EXEC_CONT void CopyVecFlatToNestedImpl(const vtkm::Vec& flatVec, vtkm::IdComponent flatOffset, NestedVecType& nestedVec) { - using Traits = vtkm::VecTraits; + using Traits = vtkm::internal::SafeVecTraits; using ComponentType = typename Traits::ComponentType; constexpr vtkm::IdComponent subSize = TotalNumComponents::value; diff --git a/vtkm/VecFromPortal.h b/vtkm/VecFromPortal.h index 9906c0e61..268da892b 100644 --- a/vtkm/VecFromPortal.h +++ b/vtkm/VecFromPortal.h @@ -91,7 +91,8 @@ struct VecTraits> using VecType = vtkm::VecFromPortal; using ComponentType = typename VecType::ComponentType; - using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; + using BaseComponentType = + typename vtkm::internal::SafeVecTraits::BaseComponentType; using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents; using IsSizeStatic = vtkm::VecTraitsTagSizeVariable; diff --git a/vtkm/VecTraits.h b/vtkm/VecTraits.h index 1d6cb1c45..440a4ced2 100644 --- a/vtkm/VecTraits.h +++ b/vtkm/VecTraits.h @@ -45,16 +45,20 @@ struct VecTraitsTagSizeVariable namespace internal { -template +// Forward declaration +template +struct SafeVecTraits; + +template struct VecTraitsMultipleComponentChooser { using Type = vtkm::VecTraitsTagMultipleComponents; }; -template <> -struct VecTraitsMultipleComponentChooser<1> +template +struct VecTraitsMultipleComponentChooser<1, ComponentType> { - using Type = vtkm::VecTraitsTagSingleComponent; + using Type = typename vtkm::internal::SafeVecTraits::HasMultipleComponents; }; } // namespace internal @@ -95,7 +99,7 @@ struct VTKM_NEVER_EXPORT VecTraits /// is really just a scalar. /// using HasMultipleComponents = - typename internal::VecTraitsMultipleComponentChooser::Type; + typename internal::VecTraitsMultipleComponentChooser::Type; /// \brief A tag specifying whether the size of this vector is known at compile time. /// @@ -197,7 +201,8 @@ template struct VecReplaceBaseComponentTypeGCC4or5 { using type = - vtkm::Vec::template ReplaceBaseComponentType, Size>; + vtkm::Vec::template ReplaceBaseComponentType, + Size>; }; } // namespace detail @@ -219,7 +224,8 @@ struct VTKM_NEVER_EXPORT VecTraits> /// Similar to ComponentType except that for nested vectors (e.g. Vec, N>), it /// returns the base scalar type at the end of the composition (T in this example). /// - using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; + using BaseComponentType = + typename vtkm::internal::SafeVecTraits::BaseComponentType; /// Number of components in the vector. /// @@ -235,7 +241,7 @@ struct VTKM_NEVER_EXPORT VecTraits> /// when a vector is really just a scalar. /// using HasMultipleComponents = - typename internal::VecTraitsMultipleComponentChooser::Type; + typename internal::VecTraitsMultipleComponentChooser::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> typename detail::VecReplaceBaseComponentTypeGCC4or5::type; #else // !GCC <= 5 template - using ReplaceBaseComponentType = vtkm::Vec< - typename vtkm::VecTraits::template ReplaceBaseComponentType, - Size>; + using ReplaceBaseComponentType = + vtkm::Vec::template ReplaceBaseComponentType, + Size>; #endif ///@}