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>