From 5773ea3e1325e6ad255f744f1ce84530b401b5a2 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 25 Feb 2020 16:45:03 -0700 Subject: [PATCH] Add porting layer for future std features Currently, VTK-m is using C++11. However, it is often useful to use features in the `std` namespace that are defined for C++14 or later. We can provide our own versions (sometimes), but it is preferable to use the version provided by the compiler if available. There were already some examples of defining portable versions of C++14 and C++17 classes in a `vtkmstd` namespace, but these were sprinkled around the source code. There is now a top level `vtkmstd` directory and in it are header files that provide portable versions of these future C++ classes. In each case, preprocessor macros are used to select which version of the class to use. --- CMakeLists.txt | 1 + docs/changelog/std_porting_headers.md | 14 ++++++ vtkm/cont/ArrayPortalToIterators.h | 25 +--------- vtkm/internal/Variant.h | 63 +----------------------- vtkmstd/CMakeLists.txt | 17 +++++++ vtkmstd/aligned_union.h | 69 +++++++++++++++++++++++++++ vtkmstd/is_trivially_copyable.h | 41 ++++++++++++++++ vtkmstd/void_t.h | 40 ++++++++++++++++ 8 files changed, 185 insertions(+), 85 deletions(-) create mode 100644 docs/changelog/std_porting_headers.md create mode 100644 vtkmstd/CMakeLists.txt create mode 100644 vtkmstd/aligned_union.h create mode 100644 vtkmstd/is_trivially_copyable.h create mode 100644 vtkmstd/void_t.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e24fd2a5..cf9b67ffc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,7 @@ check_type_size("long long" VTKm_SIZE_LONG_LONG BUILTIN_TYPES_ONLY) #----------------------------------------------------------------------------- # Add subdirectories +add_subdirectory(vtkmstd) add_subdirectory(vtkm) #----------------------------------------------------------------------------- diff --git a/docs/changelog/std_porting_headers.md b/docs/changelog/std_porting_headers.md new file mode 100644 index 000000000..8570f9308 --- /dev/null +++ b/docs/changelog/std_porting_headers.md @@ -0,0 +1,14 @@ +# Porting layer for future std features + +Currently, VTK-m is using C++11. However, it is often useful to use +features in the `std` namespace that are defined for C++14 or later. We can +provide our own versions (sometimes), but it is preferable to use the +version provided by the compiler if available. + +There were already some examples of defining portable versions of C++14 and +C++17 classes in a `vtkmstd` namespace, but these were sprinkled around the +source code. + +There is now a top level `vtkmstd` directory and in it are header files +that provide portable versions of these future C++ classes. In each case, +preprocessor macros are used to select which version of the class to use. diff --git a/vtkm/cont/ArrayPortalToIterators.h b/vtkm/cont/ArrayPortalToIterators.h index 40250cd1f..2caed28a2 100644 --- a/vtkm/cont/ArrayPortalToIterators.h +++ b/vtkm/cont/ArrayPortalToIterators.h @@ -15,30 +15,7 @@ #include -namespace vtkmstd -{ -/// Implementation of std::void_t (C++17): -/// Allows for specialization of class templates based on members of template -/// parameters. -#if defined(VTKM_GCC) && (__GNUC__ < 5) -// Due to a defect in the wording (CWG 1558) unused parameters in alias templates -// were not guaranteed to ensure SFINAE, and therefore would consider everything -// to match the 'true' side. For VTK-m the only known compiler that implemented -// this defect is GCC < 5. -template -struct void_pack -{ - using type = void; -}; -template -using void_t = typename void_pack::type; -#else -template -using void_t = void; -#endif - - -} // end namespace vtkmstd +#include namespace vtkm { diff --git a/vtkm/internal/Variant.h b/vtkm/internal/Variant.h index 8842e0f3a..4964b2035 100644 --- a/vtkm/internal/Variant.h +++ b/vtkm/internal/Variant.h @@ -15,67 +15,8 @@ #include #include -#if defined(VTKM_USING_GLIBCXX_4) -// It would make sense to put this in its own header file, but it is hard to imagine needing -// aligned_union anywhere else. -#include -namespace vtkmstd -{ - -template -struct max_size; -template -struct max_size -{ - static constexpr std::size_t value = X; -}; -template -struct max_size -{ - static constexpr std::size_t other_value = max_size::value; - static constexpr std::size_t value = (other_value > X0) ? other_value : X0; -}; - -// This is to get around an apparent bug in GCC 4.8 where alianas(x) does not -// seem to work when x is a constexpr. See -// https://stackoverflow.com/questions/29879609/g-complains-constexpr-function-is-not-a-constant-expression -template -struct aligned_data_block -{ - alignas(Alignment) char _s[Size]; -}; - -template -struct aligned_union -{ - static constexpr std::size_t alignment_value = vtkmstd::max_size::value; - - using type = - vtkmstd::aligned_data_block::value>; -}; - -// GCC 4.8 and 4.9 standard library does not support std::is_trivially_copyable. -// There is no relyable way to get this information (since it has to come special from -// the compiler). For our purposes, we will report as nothing being trivially copyable, -// which causes us to call the constructors with everything. This should be fine unless -// some other part of the compiler is trying to check for trivial copies (perhaps nvcc -// on top of GCC 4.8). -template -struct is_trivially_copyable : std::false_type -{ -}; - -} // namespace vtkmstd - -#else // NOT VTKM_USING_GLIBCXX_4 -namespace vtkmstd -{ - -using std::aligned_union; -using std::is_trivially_copyable; - -} // namespace vtkmstd -#endif +#include +#include namespace vtkm { diff --git a/vtkmstd/CMakeLists.txt b/vtkmstd/CMakeLists.txt new file mode 100644 index 000000000..01f48f3ac --- /dev/null +++ b/vtkmstd/CMakeLists.txt @@ -0,0 +1,17 @@ +##============================================================================ +## Copyright (c) Kitware, Inc. +## All rights reserved. +## See LICENSE.txt for details. +## +## This software is distributed WITHOUT ANY WARRANTY; without even +## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the above copyright notice for more information. +##============================================================================ + +set(headers + aligned_union.h + is_trivially_copyable.h + void_t.h + ) + +vtkm_declare_headers(${headers}) diff --git a/vtkmstd/aligned_union.h b/vtkmstd/aligned_union.h new file mode 100644 index 000000000..9a7a15d22 --- /dev/null +++ b/vtkmstd/aligned_union.h @@ -0,0 +1,69 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_std_aligned_union_h +#define vtk_m_std_aligned_union_h + +#include + +#include + +#if defined(VTKM_USING_GLIBCXX_4) + +#include + +namespace vtkmstd +{ + +template +struct max_size; +template +struct max_size +{ + static constexpr std::size_t value = X; +}; +template +struct max_size +{ + static constexpr std::size_t other_value = max_size::value; + static constexpr std::size_t value = (other_value > X0) ? other_value : X0; +}; + +// This is to get around an apparent bug in GCC 4.8 where alianas(x) does not +// seem to work when x is a constexpr. See +// https://stackoverflow.com/questions/29879609/g-complains-constexpr-function-is-not-a-constant-expression +template +struct aligned_data_block +{ + alignas(Alignment) char _s[Size]; +}; + +template +struct aligned_union +{ + static constexpr std::size_t alignment_value = vtkmstd::max_size::value; + + using type = + vtkmstd::aligned_data_block::value>; +}; + +} // namespace vtkmstd + +#else // NOT VTKM_USING_GLIBCXX_4 + +namespace vtkmstd +{ + +using std::aligned_union; + +} // namespace vtkmstd + +#endif // NOT VTKM_USING_GLIBCXX_4 + +#endif //vtk_m_std_aligned_union_h diff --git a/vtkmstd/is_trivially_copyable.h b/vtkmstd/is_trivially_copyable.h new file mode 100644 index 000000000..53abadab8 --- /dev/null +++ b/vtkmstd/is_trivially_copyable.h @@ -0,0 +1,41 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_std_is_trivially_copyable_h +#define vtk_m_std_is_trivially_copyable_h + +#include + +#if defined(VTKM_USING_GLIBCXX_4) +namespace vtkmstd +{ + +// GCC 4.8 and 4.9 standard library does not support std::is_trivially_copyable. +// There is no relyable way to get this information (since it has to come special from +// the compiler). For our purposes, we will report as nothing being trivially copyable, +// which causes us to call the constructors with everything. This should be fine unless +// some other part of the compiler is trying to check for trivial copies (perhaps nvcc +// on top of GCC 4.8). +template +struct is_trivially_copyable : std::false_type +{ +}; + +} // namespace vtkmstd + +#else // NOT VTKM_USING_GLIBCXX_4 +namespace vtkmstd +{ + +using std::is_trivially_copyable; + +} // namespace vtkmstd +#endif + +#endif //vtk_m_std_is_trivially_copyable_h diff --git a/vtkmstd/void_t.h b/vtkmstd/void_t.h new file mode 100644 index 000000000..acdfd4fb2 --- /dev/null +++ b/vtkmstd/void_t.h @@ -0,0 +1,40 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_std_void_t_h +#define vtk_m_std_void_t_h + +#include + +namespace vtkmstd +{ + +/// Implementation of std::void_t (C++17): +/// Allows for specialization of class templates based on members of template +/// parameters. +#if defined(VTKM_GCC) && (__GNUC__ < 5) +// Due to a defect in the wording (CWG 1558) unused parameters in alias templates +// were not guaranteed to ensure SFINAE, and therefore would consider everything +// to match the 'true' side. For VTK-m the only known compiler that implemented +// this defect is GCC < 5. +template +struct void_pack +{ + using type = void; +}; +template +using void_t = typename void_pack::type; +#else +template +using void_t = void; +#endif + +} // end namespace vtkmstd + +#endif //vtk_m_std_void_t_h