Add option to use C++11 (not TR1) shared_ptr & unordered_map.

- On at least some compilers, -std=c++11 is required in order to compile
  against std::shared_ptr & std::unordered_map, which resulted in our
  checks failing to find them and using the TR1 versions instead, which
  causes conflicts for users using C++11.
- Now, if the compiler supports it and the user enables the CXX11
  option, we explicitly enable C++11 before searching for shared_ptr &
  unordered_map, which means we should always find the C++11 versions
  if they are available.
- As use of CXX11 results in a version of Ceres that must be used with
  -std=c++11 for GCC & Clang, we roll this into the Ceres target when
  the version of CMake supports this, otherwise we warn the user they
  will have to do this themselves.
- CXX11 is OFF by default, to ensure that the behaviour of Ceres is
  unchanged from before.

Change-Id: I157ea7a4fadc6bc02da176b8e771f1f327ccaf78
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e40dd17..1812df4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -135,6 +135,7 @@
    depends on the sparse QR factorization algorithm, which is licensed
    under the MPL."
   OFF)
+OPTION(CXX11 "Enable use of C++11 if available (requires client code use C++11)." OFF)
 OPTION(BUILD_TESTING "Enable tests" ON)
 OPTION(BUILD_DOCUMENTATION "Build User's Guide (html)" OFF)
 OPTION(BUILD_EXAMPLES "Build examples" ON)
@@ -495,53 +496,38 @@
   LIST(APPEND CERES_COMPILE_OPTIONS CERES_NO_THREADS)
 ENDIF (OPENMP)
 
-INCLUDE(CheckIncludeFileCXX)
-CHECK_INCLUDE_FILE_CXX(unordered_map HAVE_STD_UNORDERED_MAP_HEADER)
-IF (HAVE_STD_UNORDERED_MAP_HEADER)
-  # Finding the unordered_map header doesn't mean that unordered_map
-  # is in std namespace.
-  #
-  # In particular, MSVC 2008 has unordered_map declared in std::tr1.
-  # In order to support this, we do an extra check to see which
-  # namespace should be used.
-  INCLUDE(CheckCXXSourceCompiles)
-  CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
-                             int main() {
-                               std::unordered_map<int, int> map;
-                               return 0;
-                             }"
-                            HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+# MSVC supports (in some sense) C++11, but does not use the -std=c++11 flag.
+INCLUDE(CheckCXXCompilerFlag)
+CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_HAS_CXX11_FLAG)
+IF (CXX11)
+  # For some compilers (at least GCC 4.8), shared_ptr & unordered_map exist in
+  # two places, as the TR1 versions are still present.  In order to avoid any
+  # conflicts in user code linking against Ceres which uses C++11, we enable
+  # C++11 (which is required when using the non-TR1 versions) if it is available
+  # before searching for shared_ptr & unordered_map.
+  IF (COMPILER_HAS_CXX11_FLAG)
+    # CMAKE_REQUIRED_FLAGS is used by CheckCXXSourceCompiles.
+    SET(CMAKE_REQUIRED_FLAGS -std=c++11)
+  ENDIF (COMPILER_HAS_CXX11_FLAG)
+ENDIF (CXX11)
+
+INCLUDE(FindUnorderedMap)
+FIND_UNORDERED_MAP()
+IF (UNORDERED_MAP_FOUND)
   IF (HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
     LIST(APPEND CERES_COMPILE_OPTIONS CERES_STD_UNORDERED_MAP)
-    MESSAGE("-- Found unordered_map/set in std namespace.")
-  ELSE (HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
-    CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
-                               int main() {
-                                 std::tr1::unordered_map<int, int> map;
-                                 return 0;
-                               }"
-                              HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
-    IF (HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
-      LIST(APPEND CERES_COMPILE_OPTIONS CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-      MESSAGE("-- Found unordered_map/set in std::tr1 namespace.")
-    ELSE (HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
-      MESSAGE("-- Found <unordered_map> but cannot find either std::unordered_map "
-              "or std::tr1::unordered_map.")
-      MESSAGE("-- Replacing unordered_map/set with map/set (warning: slower!)")
-      LIST(APPEND CERES_COMPILE_OPTIONS CERES_NO_UNORDERED_MAP)
-    ENDIF (HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
-  ENDIF (HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
-ELSE (HAVE_STD_UNORDERED_MAP_HEADER)
-  CHECK_INCLUDE_FILE_CXX("tr1/unordered_map" HAVE_TR1_UNORDERED_MAP_HEADER)
-  IF (HAVE_TR1_UNORDERED_MAP_HEADER)
+  ENDIF(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+  IF (HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+    LIST(APPEND CERES_COMPILE_OPTIONS CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+  ENDIF(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+  IF (HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE)
     LIST(APPEND CERES_COMPILE_OPTIONS CERES_TR1_UNORDERED_MAP)
-    MESSAGE("-- Found tr1/unordered_map/set in std::tr1 namespace.")
-  ELSE (HAVE_TR1_UNORDERED_MAP_HEADE)
-    MESSAGE("-- Unable to find <unordered_map> or <tr1/unordered_map>. ")
-    MESSAGE("-- Replacing unordered_map/set with map/set (warning: slower!)")
-    LIST(APPEND CERES_COMPILE_OPTIONS CERES_NO_UNORDERED_MAP)
-  ENDIF (HAVE_TR1_UNORDERED_MAP_HEADER)
-ENDIF (HAVE_STD_UNORDERED_MAP_HEADER)
+  ENDIF(HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ELSE (UNORDERED_MAP_FOUND)
+  MESSAGE("-- Replacing unordered_map/set with map/set (warning: slower!), "
+    "try enabling CXX11 option if you expect C++11 to be available.")
+  LIST(APPEND CERES_COMPILE_OPTIONS CERES_NO_UNORDERED_MAP)
+ENDIF()
 
 INCLUDE(FindSharedPtr)
 FIND_SHARED_PTR()
@@ -553,9 +539,31 @@
     LIST(APPEND CERES_COMPILE_OPTIONS CERES_TR1_SHARED_PTR)
   ENDIF (SHARED_PTR_TR1_NAMESPACE)
 ELSE (SHARED_PTR_FOUND)
-  MESSAGE(FATAL_ERROR "Unable to find shared_ptr.")
+  MESSAGE(FATAL_ERROR "Unable to find shared_ptr, try enabling CXX11 option "
+    "if you expect C++11 to be available.")
 ENDIF (SHARED_PTR_FOUND)
 
+# To ensure that CXX11 accurately captures whether we are using C++11, even on
+# MSVC, check if it is required given where the potentially C++11 features Ceres
+# uses were found, and disable it if C++11 is not being used.
+IF (CXX11)
+  IF (NOT HAVE_SHARED_PTR_IN_STD_NAMESPACE AND
+      NOT HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+    MESSAGE("-- Failed to find C++11 components in C++11 locations & "
+      "namespaces, disabling CXX11.")
+    UPDATE_CACHE_VARIABLE(CXX11 OFF)
+  ELSE()
+    MESSAGE("   ==============================================================")
+    MESSAGE("   Compiling Ceres using C++11.  This will result in a version ")
+    MESSAGE("   of Ceres that will require the use of C++11 in client code.")
+    MESSAGE("   ==============================================================")
+    LIST(APPEND CERES_COMPILE_OPTIONS CERES_USE_CXX11)
+    IF (COMPILER_HAS_CXX11_FLAG)
+      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+    ENDIF()
+  ENDIF()
+ENDIF(CXX11)
+
 INCLUDE_DIRECTORIES(
   include
   internal
diff --git a/cmake/FindSharedPtr.cmake b/cmake/FindSharedPtr.cmake
index 00d403e..3135dd5 100644
--- a/cmake/FindSharedPtr.cmake
+++ b/cmake/FindSharedPtr.cmake
@@ -40,6 +40,15 @@
 # otherwise it's assumed to be defined in std namespace.
 
 MACRO(FIND_SHARED_PTR)
+  # To support CXX11 option, clear the results of all check_xxx() functions
+  # s/t we always perform the checks each time, otherwise CMake fails to
+  # detect that the tests should be performed again after CXX11 is toggled.
+  UNSET(HAVE_STD_MEMORY_HEADER CACHE)
+  UNSET(HAVE_SHARED_PTR_IN_STD_NAMESPACE CACHE)
+  UNSET(HAVE_SHARED_PTR_IN_TR1_NAMESPACE CACHE)
+  UNSET(HAVE_TR1_MEMORY_HEADER CACHE)
+  UNSET(HAVE_SHARED_PTR_IN_TR1_NAMESPACE_FROM_TR1_MEMORY_HEADER CACHE)
+
   SET(SHARED_PTR_FOUND FALSE)
   CHECK_INCLUDE_FILE_CXX(memory HAVE_STD_MEMORY_HEADER)
   IF (HAVE_STD_MEMORY_HEADER)
diff --git a/cmake/FindUnorderedMap.cmake b/cmake/FindUnorderedMap.cmake
new file mode 100644
index 0000000..6aec18a
--- /dev/null
+++ b/cmake/FindUnorderedMap.cmake
@@ -0,0 +1,94 @@
+# Ceres Solver - A fast non-linear least squares minimizer
+# Copyright 2015 Google Inc. All rights reserved.
+# http://ceres-solver.org/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors may be
+#   used to endorse or promote products derived from this software without
+#   specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: alexs.mac@gmail.com (Alex Stewart)
+#
+
+# FindUnorderedMap.cmake - Find unordered_map header and namespace.
+#
+# This module defines the following variables:
+#
+# UNORDERED_MAP_FOUND: TRUE if unordered_map is found.
+# HAVE_UNORDERED_MAP_IN_STD_NAMESPACE: Use <unordered_map> & std.
+# HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE: Use <unordered_map> & std::tr1.
+# HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE: <tr1/unordered_map> & std::tr1.
+MACRO(FIND_UNORDERED_MAP)
+  # To support CXX11 option, clear the results of all check_xxx() functions
+  # s/t we always perform the checks each time, otherwise CMake fails to
+  # detect that the tests should be performed again after CXX11 is toggled.
+  UNSET(HAVE_STD_UNORDERED_MAP_HEADER CACHE)
+  UNSET(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE CACHE)
+  UNSET(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE CACHE)
+  UNSET(HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE CACHE)
+
+  SET(UNORDERED_MAP_FOUND FALSE)
+  INCLUDE(CheckIncludeFileCXX)
+  CHECK_INCLUDE_FILE_CXX(unordered_map HAVE_STD_UNORDERED_MAP_HEADER)
+  IF (HAVE_STD_UNORDERED_MAP_HEADER)
+    # Finding the unordered_map header doesn't mean that unordered_map
+    # is in std namespace.
+    #
+    # In particular, MSVC 2008 has unordered_map declared in std::tr1.
+    # In order to support this, we do an extra check to see which
+    # namespace should be used.
+    INCLUDE(CheckCXXSourceCompiles)
+    CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
+                               int main() {
+                                 std::unordered_map<int, int> map;
+                                 return 0;
+                               }"
+                               HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+    IF (HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+      SET(UNORDERED_MAP_FOUND TRUE)
+      MESSAGE("-- Found unordered_map/set in std namespace.")
+    ELSE (HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+      CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
+                                 int main() {
+                                   std::tr1::unordered_map<int, int> map;
+                                   return 0;
+                                 }"
+                                 HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+      IF (HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+        SET(UNORDERED_MAP_FOUND TRUE)
+        MESSAGE("-- Found unordered_map/set in std::tr1 namespace.")
+      ELSE (HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+        MESSAGE("-- Found <unordered_map> but cannot find either "
+          "std::unordered_map or std::tr1::unordered_map.")
+      ENDIF (HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
+    ENDIF (HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
+  ELSE (HAVE_STD_UNORDERED_MAP_HEADER)
+    CHECK_INCLUDE_FILE_CXX("tr1/unordered_map"
+      HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE)
+    IF (HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE)
+      SET(UNORDERED_MAP_FOUND TRUE)
+      MESSAGE("-- Found tr1/unordered_map/set in std::tr1 namespace.")
+    ELSE (HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE)
+      MESSAGE("-- Unable to find <unordered_map> or <tr1/unordered_map>.")
+    ENDIF (HAVE_TR1_UNORDERED_MAP_IN_TR1_NAMESPACE)
+  ENDIF (HAVE_STD_UNORDERED_MAP_HEADER)
+ENDMACRO(FIND_UNORDERED_MAP)
diff --git a/cmake/config.h.in b/cmake/config.h.in
index aea7921..a98fb56 100644
--- a/cmake/config.h.in
+++ b/cmake/config.h.in
@@ -60,6 +60,9 @@
 // routines.
 @CERES_NO_CUSTOM_BLAS@
 
+// If defined, Ceres was compiled with C++11.
+@CERES_USE_CXX11@
+
 // If defined, Ceres was compiled without multithreading support.
 @CERES_NO_THREADS@
 // If defined Ceres was compiled with OpenMP multithreading support.
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index f7b58e6..fc1a70b 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -52,6 +52,10 @@
 
 ADD_EXECUTABLE(curve_fitting_c curve_fitting.c)
 TARGET_LINK_LIBRARIES(curve_fitting_c ceres)
+# Force CMake to link curve_fitting_c using the C linker, this is important
+# when Ceres was compiled using C++11 to ensure that -std=c++11 is not passed
+# through.
+SET_TARGET_PROPERTIES(curve_fitting_c PROPERTIES LINKER_LANGUAGE C)
 # As this is a C file #including <math.h> we have to explicitly add the math
 # library (libm). Although some compilers (dependent upon options) will accept
 # the indirect link to libm via Ceres, at least GCC 4.8 on pure Debian won't.
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index f3df974..2d217c2 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -184,6 +184,24 @@
   VERSION ${CERES_VERSION}
   SOVERSION ${CERES_VERSION_MAJOR}
 )
+IF (CXX11 AND COMPILER_HAS_CXX11_FLAG)
+  IF (CMAKE_VERSION VERSION_LESS "2.8.12")
+    MESSAGE("-- Warning: detected CMake version: ${CMAKE_VERSION} < 2.8.12, "
+      "which is the minimum required for compile options to be included in an "
+      "exported CMake target, but CERES_USE_CXX11 is enabled and the detected. "
+      "compiler requires -std=c++11.  The client is responsible for adding "
+      "-std=c++11 when using Ceres.")
+  ELSE ()
+    # If Ceres is compiled using C++11, and the compiler requires -std=c++11
+    # to be set, then ensure that this requirement is rolled into the exported
+    # CMake target, s/t client code which uses Ceres will inherit it (if the
+    # CMake version supports it), iff they are NOT compiling for C.  We check
+    # for not C, rather than C++ as LINKER_LANGUAGE is often NOTFOUND and then
+    # uses the default (C++).
+    TARGET_COMPILE_OPTIONS(ceres PUBLIC
+      $<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>>:-std=c++11>)
+  ENDIF()
+ENDIF()
 
 IF (BUILD_SHARED_LIBS)
   # When building a shared library, mark all external libraries as