Made collections port compatible with MSVC2008

The issue was caused by the fact that in this version
of MSVC unordered_map class is defined in <unordered_map>
header file, but this file declares the class int std::tr1
namespace.

This confused existing assumption that if there's an
existing <unordered_map> file then class is declared
in std namespace.

Added an extra check to CMake which detects whether
it's std or std::tr1 which actually contains class
of unordered_map.

Change-Id: Ic5cf41913895a6ce8e791cc7602d7cf5492c34de
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ba89d02..521684c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -402,20 +402,56 @@
   ADD_DEFINITIONS(-DCERES_NO_THREADS)
 ENDIF (OPENMP)
 
-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)
-ELSE (UNORDERED_MAP_IN_STD_NAMESPACE)
+INCLUDE(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(unordered_map HAVE_STD_UNORDERED_MAP_HEADER)
+IF (HAVE_STD_UNORDERED_MAP_HEADER)
+  # Even so we've found unordered_map header file it doesn't
+  # mean unordered_map and unordered_set will be declared in
+  # std namespace.
+  #
+  # Namely, MSVC 2008 have unordered_map header which declares
+  # unordered_map class in std::tr1 namespace. In order to support
+  # this, we do extra check to see which exactly namespace is
+  # to 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)
+    ADD_DEFINITIONS(-DCERES_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)
+      ADD_DEFINITIONS(-DCERES_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!)")
+      ADD_DEFINITIONS(-DCERES_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" UNORDERED_MAP_IN_TR1_NAMESPACE)
   IF (UNORDERED_MAP_IN_TR1_NAMESPACE)
     ADD_DEFINITIONS(-DCERES_TR1_UNORDERED_MAP)
+    MESSAGE("-- Found tr1/unordered_map/set in std::tr1 namespace.")
   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)
+ENDIF (HAVE_STD_UNORDERED_MAP_HEADER)
 
 INCLUDE_DIRECTORIES(
   include
diff --git a/internal/ceres/collections_port.h b/internal/ceres/collections_port.h
index 8f345d4..e37be52 100644
--- a/internal/ceres/collections_port.h
+++ b/internal/ceres/collections_port.h
@@ -52,8 +52,17 @@
 #  define CERES_HASH_NAMESPACE_END }
 #endif
 
-#if !defined(CERES_NO_UNORDERED_MAP) && !defined(CERES_TR1_UNORDERED_MAP) && !defined(CERES_STD_UNORDERED_MAP)
-#error One of: CERES_NO_UNORDERED_MAP, CERES_TR1_UNORDERED_MAP, CERES_STD_UNORDERED_MAP must be defined!
+#if defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+#  include <unordered_map>
+#  include <unordered_set>
+#  define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 {
+#  define CERES_HASH_NAMESPACE_END } }
+#endif
+
+#if !defined(CERES_NO_UNORDERED_MAP) && !defined(CERES_TR1_UNORDERED_MAP) && \
+    !defined(CERES_STD_UNORDERED_MAP) && !defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)  // NOLINT
+#  error One of: CERES_NO_UNORDERED_MAP, CERES_TR1_UNORDERED_MAP,\
+ CERES_STD_UNORDERED_MAP, CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined!  // NOLINT
 #endif
 
 #include <utility>
@@ -82,7 +91,8 @@
 namespace ceres {
 namespace internal {
 
-#if defined(CERES_TR1_UNORDERED_MAP)
+#if defined(CERES_TR1_UNORDERED_MAP) || \
+    defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
 template<typename K, typename V>
 struct HashMap : std::tr1::unordered_map<K, V> {};
 template<typename K>