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>