Do not enforce a specific C++ standard

Current language standard selection mechanism is quite convoluted and
the logic for propagating a specific C++ language standard (which cannot
be fully enforced anyway) is unnecessarily complicated. Instead
communicate the minimum required C++ standard and let CMake handle the
requirement. This allows the compiler and consumers to use newer
language revisions if available. The language standard used to compile
Ceres solver can still be set via `CMAKE_CXX_STANDARD`.

Move to CMake 3.10 which is supported by Ubuntu 18.04 LTS and simplify
the corresponding language features request.

Change-Id: Ib1f95e2bc5f06bf1275a62565d303eb0f114d127
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 97a93e4..ef88782 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,47 +29,14 @@
 # Authors: keir@google.com (Keir Mierle)
 #          alexs.mac@gmail.com (Alex Stewart)
 
-cmake_minimum_required(VERSION 3.5)
-cmake_policy(VERSION 3.5)
-if (POLICY CMP0074)
+cmake_minimum_required(VERSION 3.10)
+
+if (POLICY CMP0074) # Added in CMake 3.12
   # FindTBB.cmake uses TBB_ROOT in a way that is historical, but also compliant
   # with CMP0074 so suppress the legacy compatibility warning and allow its use.
   cmake_policy(SET CMP0074 NEW)
 endif()
 
-# Set the C++ version when compiling Ceres.
-#
-# Reflect a user-specified (via -D) CMAKE_CXX_STANDARD if present, otherwise
-# default to C++14.
-set(DEFAULT_CXX_STANDARD ${CMAKE_CXX_STANDARD})
-if (NOT DEFAULT_CXX_STANDARD)
-  set(DEFAULT_CXX_STANDARD 14)
-endif()
-set(CMAKE_CXX_STANDARD ${DEFAULT_CXX_STANDARD} CACHE STRING
-  "C++ standard (minimum 14)" FORCE)
-# Restrict CMAKE_CXX_STANDARD to the valid versions permitted and ensure that
-# if one was forced via -D that it is in the valid set.
-set(ALLOWED_CXX_STANDARDS 14 17 20)
-set_property(CACHE CMAKE_CXX_STANDARD PROPERTY STRINGS ${ALLOWED_CXX_STANDARDS})
-list(FIND ALLOWED_CXX_STANDARDS ${CMAKE_CXX_STANDARD} POSITION)
-if (POSITION LESS 0)
-  message(FATAL_ERROR "Invalid CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}. "
-    "Must be one of: ${ALLOWED_CXX_STANDARDS}")
-endif()
-# Specify the standard as a hard requirement, otherwise CMAKE_CXX_STANDARD is
-# interpreted as a suggestion that can decay *back* to lower versions.
-set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE BOOL "")
-mark_as_advanced(CMAKE_CXX_STANDARD_REQUIRED)
-
-# MSVC versions < 2015 did not fully support >= C++14, and technically even
-# 2015 did not support a couple of smaller features
-if (CMAKE_CXX_COMPILER_ID MATCHES MSVC AND
-    CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0)
-  message(FATAL_ERROR "Invalid CMAKE_CXX_COMPILER_VERSION: "
-    "${CMAKE_CXX_COMPILER_VERSION}. Ceres requires at least MSVC 2015 for "
-    "C++14 support.")
-endif()
-
 # On macOS, add the Homebrew prefix (with appropriate suffixes) to the
 # respective HINTS directories (after any user-specified locations).  This
 # handles Homebrew installations into non-standard locations (not /usr/local).
@@ -252,7 +219,6 @@
 endif (IOS)
 
 unset(CERES_COMPILE_OPTIONS)
-message("-- Building with C++${CMAKE_CXX_STANDARD}")
 
 # Eigen.
 # Eigen delivers Eigen3Config.cmake since v3.3.3
@@ -506,6 +472,7 @@
   mark_as_advanced(benchmark_DIR)
 endif()
 
+# TODO Report features using the FeatureSummary CMake module
 if (BUILD_SHARED_LIBS)
   message("-- Building Ceres as a shared library.")
 else (BUILD_SHARED_LIBS)
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index dd3e12d..63ef44b 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -302,18 +302,12 @@
 target_compile_definitions(ceres_internal PUBLIC $<TARGET_PROPERTY:ceres,COMPILE_DEFINITIONS>)
 target_compile_options(ceres_internal PUBLIC $<TARGET_PROPERTY:ceres,COMPILE_OPTIONS>)
 target_compile_definitions(ceres_internal PRIVATE ceres_EXPORTS)
+target_compile_features(ceres_internal PRIVATE $<TARGET_PROPERTY:ceres,COMPILE_FEATURES>)
 
-# The ability to specify a minimum language version via cxx_std_[11,14,17]
-# requires CMake >= 3.8.  Prior to that we have to specify the compiler features
-# we require.
-if (CMAKE_VERSION VERSION_LESS 3.8)
-  set(REQUIRED_PUBLIC_CXX_FEATURES cxx_alignas cxx_alignof cxx_constexpr)
-else()
-  # Forward whatever C++ version Ceres was compiled with as our requirement
-  # for downstream clients.
-  set(REQUIRED_PUBLIC_CXX_FEATURES cxx_std_${CMAKE_CXX_STANDARD})
-endif()
-target_compile_features(ceres PUBLIC ${REQUIRED_PUBLIC_CXX_FEATURES})
+# 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)
 
 set_target_properties(ceres PROPERTIES
   VERSION ${CERES_VERSION}