Ceres Solver now requires C++17

Fixes https://github.com/ceres-solver/ceres-solver/issues/779

Change-Id: I6671b8da9d2004f9c76be8b03f6753c9fc5a0061
diff --git a/docs/source/installation.rst b/docs/source/installation.rst
index a59b15b..f0329f4 100644
--- a/docs/source/installation.rst
+++ b/docs/source/installation.rst
@@ -23,7 +23,7 @@
 
  .. note ::
 
-    Ceres Solver 2.1 requires a **fully C++14-compliant** compiler.
+    Ceres Solver 2.2 requires a **fully C++17-compliant** compiler.
 
 Ceres relies on a number of open source libraries, some of which are
 optional. For details on customizing the build process, see
diff --git a/include/ceres/internal/port.h b/include/ceres/internal/port.h
index 4275b0e..513bfa7 100644
--- a/include/ceres/internal/port.h
+++ b/include/ceres/internal/port.h
@@ -47,14 +47,6 @@
 #define CERES_GET_FLAG(X) X
 #endif
 
-// Indicates whether C++17 is currently active
-#ifndef CERES_HAS_CPP17
-#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
-#define CERES_HAS_CPP17
-#endif  // __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >=
-        // 201703L)
-#endif  // !defined(CERES_HAS_CPP17)
-
 // Indicates whether C++20 is currently active
 #ifndef CERES_HAS_CPP20
 #if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
diff --git a/include/ceres/jet.h b/include/ceres/jet.h
index fba1e2a..3f5311b 100644
--- a/include/ceres/jet.h
+++ b/include/ceres/jet.h
@@ -724,7 +724,6 @@
   return Jet<T, N>(tmp, x.a / tmp * x.v + y.a / tmp * y.v);
 }
 
-#ifdef CERES_HAS_CPP17
 // Like sqrt(x^2 + y^2 + z^2),
 // but acts to prevent underflow/overflow for small/large x/y/z.
 // Note that the function is non-smooth at x=y=z=0,
@@ -744,7 +743,6 @@
   const T tmp = hypot(x.a, y.a, z.a);
   return Jet<T, N>(tmp, x.a / tmp * x.v + y.a / tmp * y.v + z.a / tmp * z.v);
 }
-#endif  // defined(CERES_HAS_CPP17)
 
 // Like x * y + z but rounded only once.
 template <typename T, int N>
diff --git a/include/ceres/product_manifold.h b/include/ceres/product_manifold.h
index 33f046d..856c453 100644
--- a/include/ceres/product_manifold.h
+++ b/include/ceres/product_manifold.h
@@ -257,28 +257,15 @@
   template <typename T, std::size_t N>
   static std::array<T, N> ExclusiveScan(const std::array<T, N>& values) {
     std::array<T, N> result;
-    T init = 0;
-
-    // TODO Replace by std::exclusive_scan once C++17 is available
-    for (std::size_t i = 0; i != N; ++i) {
-      result[i] = init;
-      init += values[i];
-    }
-
+    std::exclusive_scan(values.begin(), values.end(), result.begin(), 0);
     return result;
   }
 
-  // TODO Replace by std::void_t once C++17 is available
-  template <typename... Types>
-  struct Void {
-    using type = void;
-  };
-
   template <typename T, typename E = void>
   struct IsDereferenceable : std::false_type {};
 
   template <typename T>
-  struct IsDereferenceable<T, typename Void<decltype(*std::declval<T>())>::type>
+  struct IsDereferenceable<T, std::void_t<decltype(*std::declval<T>())>>
       : std::true_type {};
 
   template <typename T,
@@ -311,7 +298,6 @@
   int tangent_size_;
 };
 
-#ifdef CERES_HAS_CPP17
 // C++17 deduction guide that allows the user to avoid explicitly specifying
 // the template parameters of ProductManifold. The class can instead be
 // instantiated as follows:
@@ -321,7 +307,6 @@
 template <typename Manifold0, typename Manifold1, typename... Manifolds>
 ProductManifold(Manifold0&&, Manifold1&&, Manifolds&&...)
     -> ProductManifold<Manifold0, Manifold1, Manifolds...>;
-#endif
 
 }  // namespace ceres
 
diff --git a/include/ceres/version.h b/include/ceres/version.h
index e0d6197..615cf62 100644
--- a/include/ceres/version.h
+++ b/include/ceres/version.h
@@ -32,7 +32,7 @@
 #define CERES_PUBLIC_VERSION_H_
 
 #define CERES_VERSION_MAJOR 2
-#define CERES_VERSION_MINOR 1
+#define CERES_VERSION_MINOR 2
 #define CERES_VERSION_REVISION 0
 
 // Classic CPP stringifcation; the extra level of indirection allows the
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index 0e33263..e60b886 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -320,7 +320,7 @@
 # Ensure the minimum required C++ language version is fulfilled as our
 # requirement by downstream clients. Consumers can choose the same or a newer
 # language standard revision.
-target_compile_features(ceres PUBLIC cxx_std_14)
+target_compile_features(ceres PUBLIC cxx_std_17)
 
 set_target_properties(ceres PROPERTIES
   VERSION ${CERES_VERSION}
diff --git a/internal/ceres/jet_test.cc b/internal/ceres/jet_test.cc
index 6f71b77..7a8be2a 100644
--- a/internal/ceres/jet_test.cc
+++ b/internal/ceres/jet_test.cc
@@ -595,7 +595,6 @@
   EXPECT_THAT(hypot(huge, J{0}), IsAlmostEqualTo(huge));
 }
 
-#ifdef CERES_HAS_CPP17
 TEST(Jet, Hypot3) {
   J zero = MakeJet(0.0, 2.0, 3.14);
 
@@ -637,8 +636,6 @@
 #endif
 }
 
-#endif  // defined(CERES_HAS_CPP17)
-
 #ifdef CERES_HAS_CPP20
 
 TEST(Jet, Lerp) {
diff --git a/internal/ceres/manifold_test.cc b/internal/ceres/manifold_test.cc
index e57eaa1..d136929 100644
--- a/internal/ceres/manifold_test.cc
+++ b/internal/ceres/manifold_test.cc
@@ -679,18 +679,8 @@
 using Eigen::Vector2d;
 using Eigen::Vector3d;
 using Vector6d = Eigen::Matrix<double, 6, 1>;
-
-// Ensure memory allocated using new in AVX2 builds is correctly aligned which
-// is only guaranteed starting with C++17. Otherwise, use unaligned memory.
-// This avoids a segmentation fault in tests that use
-// EXPECT_THAT_MANIFOLD_INVARIANTS_HOLD and fixed-size Eigen vectors.
-#ifdef CERES_HAS_CPP17
 using Eigen::Vector4d;
 using Vector8d = Eigen::Matrix<double, 8, 1>;
-#else
-using Vector4d = Eigen::Matrix<double, 4, 1, Eigen::DontAlign>;
-using Vector8d = Eigen::Matrix<double, 8, 1, Eigen::DontAlign>;
-#endif
 
 TEST(SphereManifold, ZeroTest) {
   Vector4d x{0.0, 0.0, 0.0, 1.0};