title: Error when checking the OS on C++ header file
body: <p>I have received some C++ code that I am trying to compile under Linux 64 bits using the provided makefiles.</p>
  
  <p>In that code there is a string_hash.h file containing the code:</p>
  
  <pre><code>#ifndef STRING_HASH
  #define STRING_HASH
  
  #include &lt;string&gt;
  #include "universal_hash_map.h"
  
  #ifdef WINDOWS
  typedef stdext::hash_compare&lt;std::string&gt; String_Hasher;
  typedef stdext::hash_map&lt; std::string, std::string, stdext::hash_compare&lt;std::string&gt; &gt; String_Hash;
  #else
  #ifdef LINUX
  class String_Hasher: public stdext::hash&lt; std::string &gt; {
  private:
      stdext::hash&lt;const char*&gt; hasher;
  public:
      String_Hasher() {}
      size_t operator() (const std::string&amp; p) const {
          return hasher(p.c_str());
      }
  };
  typedef stdext::hash_map&lt; std::string, std::string, String_Hasher &gt; String_Hash;
  #endif
  #endif
  
  #endif
  </code></pre>
  
  <p>With universal_hash_map.h being:</p>
  
  <pre><code>#include "define_os.h"
  
  #if defined(__MINGW32__) || defined(LINUX)
  #include&lt;ext/hash_map&gt;
  #define stdext __gnu_cxx;
  #else
  #if defined(_MSC_VER)
  #include&lt;hash_map&gt;
  #endif
  #endif
  </code></pre>
  
  <p>and define_os.h:</p>
  
  <pre><code>#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
  </code></pre>
  
  <p>If I compile the project like that I got the error telling me that the compile can not find stdext::hash</p>
  
  <pre><code>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
  </code></pre>
  
  <p>But what really puzzles me is that if I comment the first line in universal_hash_map.h so it does not include define_os.h, the code compiles fine!</p>
  
  <p>So changing universal_hash_map.h to:</p>
  
  <pre><code>//#include "define_os.h"
  
  #if defined(__MINGW32__) || defined(LINUX)
  #include&lt;ext/hash_map&gt;
  #define stdext __gnu_cxx;
  #else
  #if defined(_MSC_VER)
  #include&lt;hash_map&gt;
  #endif
  #endif
  </code></pre>
  
  <p>or just</p>
  
  <pre><code>//#include "define_os.h"
  
  //#if defined(__MINGW32__) || defined(LINUX)
  #include&lt;ext/hash_map&gt;
  #define stdext __gnu_cxx;
  //#else
  //#if defined(_MSC_VER)
  //#include&lt;hash_map&gt;
  //#endif
  //#endif
  </code></pre>
  
  <p>compiles fine.</p>
  
  <p>However in this last example, if I uncomment *#include "define_os.h"* it does not compile :s</p>
  
  <p>So the question is, why trying to define the OS make the code not to compile?</p>
  
  <p>Also, checking gcc predefined symbols it seems that there's nothing wrong there:</p>
  
  <pre><code>$ gcc -E -dM - &lt;/dev/null | grep linux
  #define __linux 1
  #define __linux__ 1
  #define __gnu_linux__ 1
  #define linux 1
  </code></pre>
  
  <p>EDIT: more info about namespaces</p>
  
  <p>In /usr/include/c++/4.7/ext/hash_map (with no file extension) I have:</p>
  
  <pre><code>#ifndef _BACKWARD_HASH_MAP
  #define _BACKWARD_HASH_MAP 1
  
  #ifndef _GLIBCXX_PERMIT_BACKWARD_HASH
  #include "backward_warning.h"
  #endif
  
  #include &lt;bits/c++config.h&gt;
  #include &lt;backward/hashtable.h&gt;
  #include &lt;bits/concept_check.h&gt;
  
  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&lt;class _Key, class _Tp, class _HashFn = hash&lt;_Key&gt;,
         class _EqualKey = equal_to&lt;_Key&gt;, class _Alloc = allocator&lt;_Tp&gt; &gt;
      class hash_map
      {
      private:
        typedef hashtable&lt;pair&lt;const _Key, _Tp&gt;,_Key, _HashFn,
              _Select1st&lt;pair&lt;const _Key, _Tp&gt; &gt;,
              _EqualKey, _Alloc&gt; _Ht;
  
        _Ht _M_ht;
  
      public:
        typedef typename _Ht::key_type key_type;
  </code></pre>
  
  <p>I don't seem to be able to find the 4.7.3 version of the code that I am running, but <a href="http://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/api/a01192_source.html" rel="nofollow">here</a> is the 4.7.2 that seems identical to me.</p>
  
  <p>EDIT:
  Files after running gcc -E on string_functions.cpp:</p>
  
  <p><a href="https://dl.dropboxusercontent.com/u/4028328/withError.txt" rel="nofollow">with error (with include)</a></p>
  
  <p><a href="https://dl.dropboxusercontent.com/u/4028328/withoutError.txt" rel="nofollow">without Error (without include)</a></p>
  
  <p><a href="https://dl.dropboxusercontent.com/u/4028328/diff.txt" rel="nofollow">diff</a></p>