From a26d05bda264d8d994061440e5dcf8926f2927bb Mon Sep 17 00:00:00 2001
From: Simon Praetorius <simon.praetorius@tu-dresden.de>
Date: Sat, 6 Mar 2021 00:41:41 +0100
Subject: [PATCH] remove cxx feature checks that are already in c++17 standard
 library

Add Changelog entry
---
 CHANGELOG.md                         |  9 +++
 cmake/modules/CheckCXXFeatures.cmake | 82 -------------------------
 config.h.cmake                       | 25 ++------
 dune/common/std/apply.hh             | 43 +-------------
 dune/common/std/make_array.hh        |  2 +
 dune/common/std/type_traits.hh       | 24 +-------
 dune/common/typetraits.hh            | 89 ----------------------------
 7 files changed, 23 insertions(+), 251 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index faf6fe13d..f5c56f84f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
 # Master (will become release 2.8)
 
+- Deprecate fallback implementations `Dune::Std::apply`, `Dune::Std::bool_constant`, and
+  `Dune::Std::make_array` in favor of std c++ implementations.
+
+- Remove c++ feature tests in cmake for existing c++-17 standards. Add default
+  defines for `DUNE_HAVE_CXX_BOOL_CONSTANT`, `DUNE_HAVE_CXX_EXPERIMENTAL_BOOL_CONSTANT`,
+  `DUNE_HAVE_HEADER_EXPERIMENTAL_TYPE_TRAITS`, `DUNE_HAVE_CXX_APPLY`,
+  `DUNE_HAVE_CXX_EXPERIMENTAL_APPLY`, `HAVE_IS_INDEXABLE_SUPPORT` in `config.h` for one
+  more release.
+
 - Add backport of `FindPkgConfig.cmake` from cmake 3.19.4 since there was a bug in
   an older find module leading to problems finding tbb in debian:10.
 
diff --git a/cmake/modules/CheckCXXFeatures.cmake b/cmake/modules/CheckCXXFeatures.cmake
index 455c2ae15..2f1747625 100644
--- a/cmake/modules/CheckCXXFeatures.cmake
+++ b/cmake/modules/CheckCXXFeatures.cmake
@@ -264,54 +264,6 @@ check_cxx_source_compiles("
 "  HAS_ATTRIBUTE_DEPRECATED_MSG
 )
 
-# full support for is_indexable (checking whether a type supports operator[])
-check_cxx_source_compiles("
-  #include <utility>
-  #include <type_traits>
-  #include <array>
-
-  template <class T>
-  typename std::add_rvalue_reference<T>::type declval();
-
-  namespace detail {
-
-    template<typename T, typename I, typename = int>
-    struct _is_indexable
-      : public std::false_type
-    {};
-
-    template<typename T, typename I>
-    struct _is_indexable<T,I,typename std::enable_if<(sizeof(declval<T>()[declval<I>()]) > 0),int>::type>
-      : public std::true_type
-    {};
-
-  }
-
-  template<typename T, typename I = std::size_t>
-  struct is_indexable
-    : public detail::_is_indexable<T,I>
-  {};
-
-  struct foo_type {};
-
-  int main()
-  {
-    double x;
-    std::array<double,4> y;
-    double z[5];
-    foo_type f;
-
-    static_assert(not is_indexable<decltype(x)>::value,\"scalar type\");
-    static_assert(is_indexable<decltype(y)>::value,\"indexable class\");
-    static_assert(is_indexable<decltype(z)>::value,\"array\");
-    static_assert(not is_indexable<decltype(f)>::value,\"not indexable class\");
-    static_assert(not is_indexable<decltype(y),foo_type>::value,\"custom index type\");
-
-    return 0;
-  }
-" HAVE_IS_INDEXABLE_SUPPORT
-  )
-
 # ******************************************************************************
 #
 # Checks for standard library features
@@ -326,40 +278,6 @@ check_cxx_source_compiles("
 #
 # ******************************************************************************
 
-# Check whether we have <experimental/type_traits> (for is_detected et. al.)
-check_include_file_cxx(
-  experimental/type_traits
-  DUNE_HAVE_HEADER_EXPERIMENTAL_TYPE_TRAITS
-  )
-
-check_cxx_symbol_exists(
-  "std::move<std::bool_constant<true>>"
-  "utility;type_traits"
-  DUNE_HAVE_CXX_BOOL_CONSTANT
-  )
-
-if (NOT DUNE_HAVE_CXX_BOOL_CONSTANT)
-  check_cxx_symbol_exists(
-    "std::move<std::experimental::bool_constant<true>>"
-    "utility;experimental/type_traits"
-    DUNE_HAVE_CXX_EXPERIMENTAL_BOOL_CONSTANT
-    )
-endif()
-
-check_cxx_symbol_exists(
-  "std::apply<std::negate<int>,std::tuple<int>>"
-  "functional;tuple"
-  DUNE_HAVE_CXX_APPLY
-  )
-
-if (NOT DUNE_HAVE_CXX_APPLY)
-  check_cxx_symbol_exists(
-    "std::experimental::apply<std::negate<int>,std::tuple<int>>"
-    "functional;experimental/tuple"
-    DUNE_HAVE_CXX_EXPERIMENTAL_APPLY
-  )
-endif()
-
 check_cxx_symbol_exists(
   "std::experimental::make_array<int,int>"
   "experimental/array"
diff --git a/config.h.cmake b/config.h.cmake
index 9925dab4d..e70632668 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -29,21 +29,6 @@
 /* does the compiler support __attribute__((unused))? */
 #cmakedefine HAS_ATTRIBUTE_UNUSED 1
 
-/* does the standard library provide <experimental/type_traits> ? */
-#cmakedefine DUNE_HAVE_HEADER_EXPERIMENTAL_TYPE_TRAITS 1
-
-/* does the standard library provide bool_constant ? */
-#cmakedefine DUNE_HAVE_CXX_BOOL_CONSTANT 1
-
-/* does the standard library provide experimental::bool_constant ? */
-#cmakedefine DUNE_HAVE_CXX_EXPERIMENTAL_BOOL_CONSTANT 1
-
-/* does the standard library provide apply() ? */
-#cmakedefine DUNE_HAVE_CXX_APPLY 1
-
-/* does the standard library provide experimental::apply() ? */
-#cmakedefine DUNE_HAVE_CXX_EXPERIMENTAL_APPLY 1
-
 /* does the standard library provide experimental::make_array() ? */
 #cmakedefine DUNE_HAVE_CXX_EXPERIMENTAL_MAKE_ARRAY 1
 
@@ -129,10 +114,12 @@
 #define DUNE_HAVE_CXX_VARIANT 1
 #define DUNE_SUPPORTS_CXX_THROW_IN_CONSTEXPR 1
 #define DUNE_HAVE_C_ALIGNED_ALLOC 1
-
-
-/* Define to 1 if the compiler properly supports testing for operator[] */
-#cmakedefine HAVE_IS_INDEXABLE_SUPPORT 1
+#define DUNE_HAVE_CXX_BOOL_CONSTANT 1
+#define DUNE_HAVE_CXX_EXPERIMENTAL_BOOL_CONSTANT 0
+#define DUNE_HAVE_HEADER_EXPERIMENTAL_TYPE_TRAITS 0
+#define DUNE_HAVE_CXX_APPLY 1
+#define DUNE_HAVE_CXX_EXPERIMENTAL_APPLY 0
+#define HAVE_IS_INDEXABLE_SUPPORT 1
 
 /* Define to ENABLE_UMFPACK if the UMFPack library is available */
 #cmakedefine HAVE_UMFPACK ENABLE_SUITESPARSE
diff --git a/dune/common/std/apply.hh b/dune/common/std/apply.hh
index aa0b6293a..483ff8138 100644
--- a/dune/common/std/apply.hh
+++ b/dune/common/std/apply.hh
@@ -3,54 +3,17 @@
 #ifndef DUNE_COMMON_STD_APPLY_HH
 #define DUNE_COMMON_STD_APPLY_HH
 
-#if DUNE_HAVE_CXX_APPLY
-  #include <tuple>
-#elif DUNE_HAVE_CXX_EXPERIMENTAL_APPLY
-  #include <experimental/tuple>
-#else
-  #include <cstddef>
-  #include <utility>
-  #include <tuple>
-#endif
-
-#include <dune/common/tupleutility.hh>
-
+#include <tuple>
 
 namespace Dune
 {
-
   namespace Std
   {
 
-#if DUNE_HAVE_CXX_APPLY
-
+    /// Invoke the Callable object f with a tuple of arguments.
+    /// \deprecated Use `std::apply` directly.
     using std::apply;
 
-#elif DUNE_HAVE_CXX_EXPERIMENTAL_APPLY
-
-    using std::experimental::apply;
-
-#else
-
-    /**
-     * \brief Apply function with arguments given as tuple
-     *
-     * \param f A callable object
-     * \param args Tuple of arguments
-     *
-     * This will call the function with arguments generated by unpacking the tuple.
-     *
-     * \ingroup CxxUtilities
-     */
-    template<class F, class ArgTuple>
-    decltype(auto) apply(F&& f, ArgTuple&& args)
-    {
-      auto indices = std::make_index_sequence<std::tuple_size<std::decay_t<ArgTuple>>::value>();
-      return applyPartial(std::forward<F>(f), std::forward<ArgTuple>(args), indices);
-    }
-
-#endif
-
   } // namespace Std
 } // namespace Dune
 
diff --git a/dune/common/std/make_array.hh b/dune/common/std/make_array.hh
index afe5418c5..cdea32331 100644
--- a/dune/common/std/make_array.hh
+++ b/dune/common/std/make_array.hh
@@ -13,6 +13,7 @@ namespace Std {
 
 #if DUNE_HAVE_CXX_EXPERIMENTAL_MAKE_ARRAY
 
+  /// \deprecated Use deduction guide of `std::array` or `std::to_array`.
   using std::experimental::make_array;
 
 #else // DUNE_HAVE_CXX_EXPERIMENTAL_MAKE_ARRAY
@@ -30,6 +31,7 @@ namespace Std {
    *       give a diagnostic when anyone happens to do that.
    *
    * \ingroup CxxUtilities
+   * \deprecated Use deduction guide of `std::array` or `std::to_array`.
    */
   template <typename... Args>
   std::array<typename std::common_type<Args...>::type, sizeof...(Args)>
diff --git a/dune/common/std/type_traits.hh b/dune/common/std/type_traits.hh
index d7bdfb7d1..8c19b30d5 100644
--- a/dune/common/std/type_traits.hh
+++ b/dune/common/std/type_traits.hh
@@ -97,27 +97,9 @@ namespace Std
   struct to_true_type : public std::true_type {};
 
 
-#if DUNE_HAVE_CXX_BOOL_CONSTANT
-
-    using std::bool_constant;
-
-#elif DUNE_HAVE_CXX_EXPERIMENTAL_BOOL_CONSTANT
-
-    using std::experimental::bool_constant;
-
-#else
-
-    /**
-     *  \brief A template alias for std::integral_constant<bool, value>
-     *
-     *  \tparam value Boolean value to encode as std::integral_constant<bool, value>
-     *
-     * \ingroup CxxUtilities
-     */
-    template <bool value>
-    using bool_constant = std::integral_constant<bool, value>;
-
-#endif
+  /// A helper alias template std::bool_constant imported into the namespace Dune::Std
+  /// \deprecated Use the `std::bool_constant` directly.
+  using std::bool_constant;
 
 
   namespace Impl {
diff --git a/dune/common/typetraits.hh b/dune/common/typetraits.hh
index 77eb25aef..468c24a02 100644
--- a/dune/common/typetraits.hh
+++ b/dune/common/typetraits.hh
@@ -197,8 +197,6 @@ namespace Dune
   struct [[deprecated("Has been renamed to 'HasNaN'.")]] has_nan
     : HasNaN<T> {};
 
-#if defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT
-
 #ifndef DOXYGEN
 
   namespace Impl {
@@ -227,95 +225,8 @@ namespace Dune
     : public Impl::IsIndexable<T,I>
   {};
 
-#else // defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT
-
-
-  // okay, here follows a mess of compiler bug workarounds...
-  // GCC 4.4 dies if we try to subscript a simple type like int and
-  // both GCC 4.4 and 4.5 don't like using arbitrary types as subscripts
-  // for macros.
-  // So we make sure to only ever attempt the SFINAE for operator[] for
-  // class types, and to make sure the compiler doesn't become overly eager
-  // we have to do some lazy evaluation tricks with nested templates and
-  // stuff.
-  // Let's get rid of GCC 4.4 ASAP!
-
-
-  namespace Impl {
-
-    // simple wrapper template to support the lazy evaluation required
-    // in _is_indexable
-    template<typename T>
-    struct _lazy
-    {
-      template<typename U>
-      struct evaluate
-      {
-        typedef T type;
-      };
-    };
-
-    // default version, gets picked if SFINAE fails
-    template<typename T, typename = int>
-    struct IsIndexable
-      : public std::false_type
-    {};
-
-    // version for types supporting the subscript operation
-    template<typename T>
-    struct IsIndexable<T,decltype(std::declval<T>()[0],0)>
-      : public std::true_type
-    {};
-
-    // helper struct for delaying the evaluation until we are sure
-    // that T is a class (i.e. until we are outside std::conditional
-    // below)
-    struct _check_for_index_operator
-    {
-
-      template<typename T>
-      struct evaluate
-        : public IsIndexable<T>
-      {};
-
-    };
-
-  }
-
-  // The rationale here is as follows:
-  // 1) If we have an array, we assume we can index into it. That isn't
-  //    true if I isn't an integral type, but that's why we have the static assertion
-  //    in the body - we could of course try and check whether I is integral, but I
-  //    can't be arsed and want to provide a motivation to switch to a newer compiler...
-  // 2) If we have a class, we use SFINAE to check for operator[]
-  // 3) Otherwise, we assume that T does not support indexing
-  //
-  // In order to make sure that the compiler doesn't accidentally try the SFINAE evaluation
-  // on an array or a scalar, we have to resort to lazy evaluation.
-  template<typename T, typename I = std::size_t>
-  struct IsIndexable
-    : public std::conditional<
-               std::is_array<T>::value,
-               Impl::_lazy<std::true_type>,
-               typename std::conditional<
-                 std::is_class<T>::value,
-                 Impl::_check_for_index_operator,
-                 Impl::_lazy<std::false_type>
-                 >::type
-               >::type::template evaluate<T>::type
-  {
-    static_assert(std::is_same<I,std::size_t>::value,"Your compiler is broken and does not support checking for arbitrary index types");
-  };
-
-
-#endif // defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT
-
   //! Type trait to determine whether an instance of T has an operator[](I), i.e. whether it can be indexed with an index of type I.
   //! \deprecated is_indexable is deprecated, use `Dune::IsIndexable` instead
-  /**
-   * \warning Not all compilers support testing for arbitrary index types. In particular, there
-   *          are problems with GCC 4.4 and 4.5.
-   */
   template<typename T, typename I = std::size_t>
   struct [[deprecated("Has been renamed to 'IsIndexable'.")]] is_indexable
     : public IsIndexable<T,I> {};
-- 
GitLab