From bd5b84fa90fd8d41e1bcd65d7ca46f36b4eaee50 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 22 Feb 2021 08:49:41 -0700 Subject: [PATCH] Have VTKM_IS_TRIVIAL* macros show types better Changed the definition of `VTKM_IS_TRIVIAL`, `VTKM_IS_TRIVIALLY_COPYABLE` and the like to use internal structs to do the static assert rather than have them do the static assert themselves. This makes the compiler more likely to tell you the actual type being checked rather. (At least, this was the case on my clang compiler.) --- vtkmstd/is_trivial.h | 64 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/vtkmstd/is_trivial.h b/vtkmstd/is_trivial.h index 0501243d6..c54e3f4a2 100644 --- a/vtkmstd/is_trivial.h +++ b/vtkmstd/is_trivial.h @@ -55,10 +55,10 @@ struct is_trivial : std::false_type // `VTKM_IS_TRIVIALLY_COPYABLE`, which will always pass on compilers that don't // support is_trivially_copyable, but will do the correct check on compilers that // do support it. -#define VTKM_IS_TRIVIALLY_COPYABLE(type) VTKM_STATIC_ASSERT(true) +#define VTKM_IS_TRIVIALLY_COPYABLE(...) VTKM_STATIC_ASSERT(true) #define VTKM_IS_TRIVIALLY_CONSTRUCTIBLE(...) VTKM_STATIC_ASSERT(true) #define VTKM_IS_TRIVIALLY_DESTRUCTIBLE(...) VTKM_STATIC_ASSERT(true) -#define VTKM_IS_TRIVIAL(type) VTKM_STATIC_ASSERT(true) +#define VTKM_IS_TRIVIAL(...) VTKM_STATIC_ASSERT(true) } // namespace vtkmstd @@ -71,18 +71,54 @@ using std::is_trivially_constructible; using std::is_trivially_copyable; using std::is_trivially_destructible; -#define VTKM_IS_TRIVIALLY_COPYABLE(type) \ - VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_copyable::value, \ - "Type must be trivially copyable to be used here.") -#define VTKM_IS_TRIVIALLY_CONSTRUCTIBLE(...) \ - VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_constructible<__VA_ARGS__>::value, \ - "Type must be trivially constructible to be used here.") -#define VTKM_IS_TRIVIALLY_DESTRUCTIBLE(...) \ - VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_destructible<__VA_ARGS__>::value, \ - "Type must be trivially constructible to be used here.") -#define VTKM_IS_TRIVIAL(type) \ - VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivial::value, \ - "Type must be trivial to be used here.") +namespace detail +{ + +// Note: the reason why we redirect the trivial checks to these classes is so when the checks +// fail it is easier to read from the error messages exactly which type was being checked. If +// you just do a static assert in a macro, the error message is likely to give you either +// macro argument names or unresolved types in the error message, which is unhelpful. + +template +struct CheckTriviallyCopyable +{ + VTKM_STATIC_ASSERT_MSG(vtkmstd::is_trivially_copyable::value, + "Type must be trivially copyable to be used here."); + static constexpr bool value = true; +}; + +template +struct CheckTriviallyConstructible +{ + VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_constructible::value, + "Type must be trivially constructible to be used here."); + static constexpr bool value = true; +}; + +template +struct CheckTriviallyDestructible +{ + VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_destructible::value, + "Type must be trivially destructible to be used here."); + static constexpr bool value = true; +}; + +template +struct CheckTrivial +{ + VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivial::value, "Type must be trivial to be used here."); + static constexpr bool value = true; +}; + +} // namespace detail + +#define VTKM_IS_TRIVIALLY_COPYABLE(...) \ + VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTriviallyCopyable<__VA_ARGS__>::value) +#define VTKM_IS_TRIVIALLY_CONSTRUCTIBLE(...) \ + VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTriviallyConstructible<__VA_ARGS__>::value) +#define VTKM_IS_TRIVIALLY_DESTRUCTIBLE(...) \ + VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTriviallyDestructible<__VA_ARGS__>::value) +#define VTKM_IS_TRIVIAL(...) VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTrivial<__VA_ARGS__>::value) } // namespace vtkmstd #endif