0

提供された makefile を使用して Linux 64 ビットでコンパイルしようとしている C++ コードを受け取りました。

そのコードには、次のコードを含む string_hash.h ファイルがあります。

#ifndef STRING_HASH
#define STRING_HASH

#include <string>
#include "universal_hash_map.h"

#ifdef WINDOWS
typedef stdext::hash_compare<std::string> String_Hasher;
typedef stdext::hash_map< std::string, std::string, stdext::hash_compare<std::string> > String_Hash;
#else
#ifdef LINUX
class String_Hasher: public stdext::hash< std::string > {
private:
    stdext::hash<const char*> hasher;
public:
    String_Hasher() {}
    size_t operator() (const std::string& p) const {
        return hasher(p.c_str());
    }
};
typedef stdext::hash_map< std::string, std::string, String_Hasher > String_Hash;
#endif
#endif

#endif

universal_hash_map.h の場合:

#include "define_os.h"

#if defined(__MINGW32__) || defined(LINUX)
#include<ext/hash_map>
#define stdext __gnu_cxx;
#else
#if defined(_MSC_VER)
#include<hash_map>
#endif
#endif

そしてdefine_os.h:

#if defined(WINDOWS) || defined(LINUX)
#else

#if defined(_MSC_VER) || defined(WIN32)  || defined(_WIN32) || defined(__WIN32__) \
|| defined(WIN64)     || defined(_WIN64) || defined(__WIN64__)
#define WINDOWS
#elif defined(sun)       || defined(__sun)      || defined(linux)       || defined(__linux) \
 || defined(__linux__)   || defined(__CYGWIN__) || defined(BSD)         || defined(__FreeBSD__) \
 || defined(__OPENBSD__) || defined(__MACOSX__) || defined(__APPLE__)   || defined(sgi) \
 || defined(__sgi)
#define LINUX
#endif

#endif

そのようにプロジェクトをコンパイルすると、コンパイルで stdext::hash が見つからないというエラーが表示されます

Compiling string_functions.o from /home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_functions.cpp.
In file included from /home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_functions.h:5:0,
                 from /home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_functions.cpp:1:
/home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_hash.h:12:29: error: expected class-name before ‘;’ token
/home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_hash.h:12:29: error: expected ‘{’ before ‘;’ token
/home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_hash.h:12:35: error: ‘hash’ in namespace ‘::’ does not name a type
/home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_hash.h:21:9: error: ‘__gnu_cxx’ does not name a type
/home/adria/Code/JensAdria/trunk/thirdparty/pechin/Cpp_Libraries/mylibrary/codes/string_hash.h:21:15: error: ‘hash_map’ in namespace ‘::’ does not name a type
make: *** [string_functions.o] Error 1

しかし、本当に困惑しているのは、universal_hash_map.h の最初の行にコメントを付けて、define_os.h を含めないようにすると、コードが正常にコンパイルされることです。

したがって、universal_hash_map.h を次のように変更します。

//#include "define_os.h"

#if defined(__MINGW32__) || defined(LINUX)
#include<ext/hash_map>
#define stdext __gnu_cxx;
#else
#if defined(_MSC_VER)
#include<hash_map>
#endif
#endif

あるいは単に

//#include "define_os.h"

//#if defined(__MINGW32__) || defined(LINUX)
#include<ext/hash_map>
#define stdext __gnu_cxx;
//#else
//#if defined(_MSC_VER)
//#include<hash_map>
//#endif
//#endif

正常にコンパイルされます。

ただし、この最後の例では、*#include "define_os.h"* のコメントを外すと、コンパイルされません:s

問題は、なぜ OS を定義しようとするとコードがコンパイルされないのかということです。

また、gcc の定義済みシンボルをチェックすると、そこには何も問題がないようです。

$ gcc -E -dM - </dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

編集:名前空間に関する詳細情報

/usr/include/c++/4.7/ext/hash_map (ファイル拡張子なし) には次のものがあります。

#ifndef _BACKWARD_HASH_MAP
#define _BACKWARD_HASH_MAP 1

#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH
#include "backward_warning.h"
#endif

#include <bits/c++config.h>
#include <backward/hashtable.h>
#include <bits/concept_check.h>

namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  using std::equal_to;
  using std::allocator;
  using std::pair;
  using std::_Select1st;

  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
   */
  template<class _Key, class _Tp, class _HashFn = hash<_Key>,
       class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> >
    class hash_map
    {
    private:
      typedef hashtable<pair<const _Key, _Tp>,_Key, _HashFn,
            _Select1st<pair<const _Key, _Tp> >,
            _EqualKey, _Alloc> _Ht;

      _Ht _M_ht;

    public:
      typedef typename _Ht::key_type key_type;

私が実行しているコードの 4.7.3 バージョンを見つけることができないようですが、これ私と同じように見える 4.7.2 です。

編集: string_functions.cpp で gcc -E を実行した後のファイル:

エラーあり(インクルードあり)

エラーなし (インクルードなし)

差分

4

1 に答える 1