Fix handling of unordered_map/unordered_set on OSX 10.9.0.

Depending on the compiler + standard library combination,
unordered_map/set may or may not be available. If available
they maybe in the std or the std::tr1 namespaces.

Apple switched to using libc++ with 10.9.0 which places
unordered_map in std, breaking our assumptions about the
platform.

This change refactors our logic for dealing with the namespace
switching, making it a three state thing rather than two. There
are three defines now, CERES_NO_UNORDERED_MAP, CERES_STD_UNORDERED_MAP
and CERES_TR1_UNORDERED_MAP. Earlier the first two were conflated
into one, leading to the breakage.

Change-Id: I904fe8c49529169bdefa9f2ee6d629e7eab0b855
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 75967f2..7519f48 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -104,9 +104,7 @@
 # Multithreading using OpenMP
 OPTION(OPENMP "Enable threaded solving in Ceres (requires OpenMP)" ON)
 # TODO(sameeragarwal): Replace this with a positive option instead?
-OPTION(DISABLE_TR1
-       "Don't use TR1. This replaces some hash tables with sets. Slower."
-       OFF)
+
 # Line search minimizer is useful for large scale problems or when
 # sparse linear algebra libraries are not available. If compile time,
 # binary size or compiler performance is an issue, consider disabling
@@ -409,37 +407,24 @@
   ADD_DEFINITIONS(-DCERES_NO_THREADS)
 ENDIF (OPENMP)
 
-IF (DISABLE_TR1)
-  MESSAGE("-- Replacing unordered_map/set with map/set (warning: slower!)")
-  ADD_DEFINITIONS(-DCERES_NO_TR1)
-ELSE (DISABLE_TR1)
-  MESSAGE("-- Using normal TR1 unordered_map/set")
-  # Use the std namespace for the hash<> and related templates. This may vary by
-  # system.
-  IF (MSVC)
-    IF (MSVC90)
-      # Special case for Visual Studio 2008.
-      # Newer versions have got tr1 symbols in another namespace,
-      # and this is being handled in Else branch of this condition.
-      # Probably Visual studio 2003 and 2005 also shall be handled here,
-      # but don't have by hand to verify and most likely they're not
-      # used by Ceres users anyway.
-      ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {\"")
-      ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_END=}}\"")
-    ELSE (MSVC90)
-      # This is known to work with Visual Studio 2010 Express.
-      # Further, for as long Visual Studio 2012 didn't move tr1 to
-      # just another namespace, the same define will work for it as well.
-      # Hopefully all further versions will also keep working with this define.
-      ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_START=namespace std {\"")
-      ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_END=}\"")
-    ENDIF(MSVC90)
-  ELSE (MSVC)
-    # This is known to work with recent versions of Linux and Mac OS X.
+Include(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(unordered_map UNORDERED_MAP_IN_STD_NAMESPACE)
+If (UNORDERED_MAP_IN_STD_NAMESPACE)
+  ADD_DEFINITIONS(-DCERES_STD_UNORDERED_MAP)
+  ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_START=namespace std {\"")
+  ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_END=}\"")
+ELSE (UNORDERED_MAP_IN_STD_NAMESPACE)
+  CHECK_INCLUDE_FILE_CXX("tr1/unordered_map" UNORDERED_MAP_IN_TR1_NAMESPACE)
+  IF (UNORDERED_MAP_IN_TR1_NAMESPACE)
+    ADD_DEFINITIONS(-DCERES_TR1_UNORDERED_MAP)
     ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {\"")
     ADD_DEFINITIONS("\"-DCERES_HASH_NAMESPACE_END=}}\"")
-  ENDIF (MSVC)
-ENDIF (DISABLE_TR1)
+  ELSE (UNORDERED_MAP_IN_TR1_NAMESPACE)
+    MESSAGE("-- Unable to find <unordered_map> or <tr1/unordered_map>. ")
+    MESSAGE("-- Replacing unordered_map/set with map/set (warning: slower!)")
+    ADD_DEFINITIONS(-DCERES_NO_UNORDERED_MAP)
+  ENDIF (UNORDERED_MAP_IN_TR1_NAMESPACE)
+ENDIF (UNORDERED_MAP_IN_STD_NAMESPACE)
 
 INCLUDE_DIRECTORIES(
   include
diff --git a/internal/ceres/collections_port.h b/internal/ceres/collections_port.h
index 715c975..ae71e54 100644
--- a/internal/ceres/collections_port.h
+++ b/internal/ceres/collections_port.h
@@ -33,26 +33,30 @@
 #ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_
 #define CERES_INTERNAL_COLLECTIONS_PORT_H_
 
-#if defined(CERES_NO_TR1)
+#if defined(CERES_NO_UNORDERED_MAP)
 #  include <map>
 #  include <set>
-#else
-#  if defined(_MSC_VER)
-#    include <unordered_map>
-#    include <unordered_set>
-#  else
-#    include <tr1/unordered_map>
-#    include <tr1/unordered_set>
-#  endif
 #endif
+
+#if defined(CERES_TR1_UNORDERED_MAP)
+#  include <tr1/unordered_map>
+#  include <tr1/unordered_set>
+#endif
+
+#if defined(CERES_STD_UNORDERED_MAP)
+#  include <unordered_map>
+#  include <unordered_set>
+#endif
+
+
 #include <utility>
 #include "ceres/integral_types.h"
 #include "ceres/internal/port.h"
 
-// Some systems don't have access to TR1. In that case, substitute the hash
-// map/set with normal map/set. The price to pay is slightly slower speed for
-// some operations.
-#if defined(CERES_NO_TR1)
+// Some systems don't have access to unordered_map/unordered_set. In
+// that case, substitute the hash map/set with normal map/set. The
+// price to pay is slightly slower speed for some operations.
+#if defined(CERES_NO_UNORDERED_MAP)
 
 namespace ceres {
 namespace internal {
@@ -71,11 +75,19 @@
 namespace ceres {
 namespace internal {
 
+#if defined(CERES_TR1_UNORDERED_MAP)
 template<typename K, typename V>
 struct HashMap : std::tr1::unordered_map<K, V> {};
-
 template<typename K>
 struct HashSet : std::tr1::unordered_set<K> {};
+#endif
+
+#if defined(CERES_STD_UNORDERED_MAP)
+template<typename K, typename V>
+struct HashMap : std::unordered_map<K, V> {};
+template<typename K>
+struct HashSet : std::unordered_set<K> {};
+#endif
 
 #if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__)
 #define GG_LONGLONG(x) x##I64
@@ -162,6 +174,5 @@
 
 CERES_HASH_NAMESPACE_END
 
-#endif  // CERES_NO_TR1
-
+#endif  // CERES_NO_UNORDERED_MAP
 #endif  // CERES_INTERNAL_COLLECTIONS_PORT_H_
diff --git a/jni/Android.mk b/jni/Android.mk
index 1c6f045..c68f79b 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -104,7 +104,7 @@
                 -DCERES_NO_GFLAGS \
                 -DCERES_NO_THREADS \
                 -DCERES_NO_CXSPARSE \
-                -DCERES_NO_TR1 \
+                -DCERES_NO_UNORDERED_MAP \
                 -DCERES_WORK_AROUND_ANDROID_NDK_COMPILER_BUG
 
 # On Android NDK 8b, GCC gives spurrious warnings about ABI incompatibility for