Boost logo

Boost :

From: Alan Bellingham (alan_at_[hidden])
Date: 2002-02-23 14:35:56


"David Abrahams" <david.abrahams_at_[hidden]>:

>From: "Alan Bellingham" <alan_at_[hidden]>
>
>> I dislike header files introducing macros for mixed or lower case
>> identifiers, because of the preprocessor's disregard for scope, so I
>> actually have a 40,000 line header file that undefines all such macros
>> introduced by the Win32 API headers and a shorter file that applies
>> inline overloads as above, on a case by case basis.
>
>Any chance you can make this available for general use? It would be a great
>service to the C++ community.

I have already had a request to write this up for Overload, and I'm
looking for the suitable round tuit ...

The 40KLOC undefs.h header is auto-generated using a Perl script (and is
somewhat bloated as a result, since multiple definitions occur in the
headers). _All_ it contains is entries like:

  #if defined(GetFileAttributes)
  # undef GetFileAttributes
  #endif // defined(GetFileAttributes)

The redefs.h header then contains:

  inline DWORD GetFileAttributes(char const* FileName)
  {
     return GetFileAttributesA(FileName) ;
  }
  inline DWORD GetFileAttributes(wchar_t const* FileName)
  {
     return GetFileAttributesW(FileName) ;
  }

but only for those functions I currently use, so it's a small subset of
the entire possible content - as I encounter a Win32 API function that
isn't yet in it, I then include it.

At the moment, the sheer size of the headers is a bit of a pain - it
works fine with C++ Builder and precompiled headers, but since it
attempts to 'fix' every header I found, it's unnecessarily messy. It
works best with all relevant Win32 headers preincluded, which is not a
terribly good idea, as any Win32 header included afterwards is going to
mess it up.

At the moment, I'm looking at producing a set of headers - an undef and
redef pair to shadow each Win32 header - and including those actually
required.

  // user's source file
  #include <winbase.h>
  #include ... // all other Win32 headers used
  #include "undefs.h"
  #include "redefs.h"
  #include ... // all other headers required

  // undefs.h
  #if defined(INC_WINBASE_H) // or whatever the guard actually is ...
  # include "undef_winbase.h"
  #endif
  
  // redefs.h
  #if defined(INC_WINBASE_H) // or whatever the guard actually is ...
  # include "redef_winbase.h"
  #endif
  
  // undef_winbase.h
  #if defined(GetFileAttributes)
  # undef GetFileAttributes
  #endif // defined(GetFileAttributes)

  // redef_winbase.h
  inline DWORD GetFileAttributes(char const* FileName)
  {
     return GetFileAttributesA(FileName) ;
  }
  inline DWORD GetFileAttributes(wchar_t const* FileName)
  {
     return GetFileAttributesW(FileName) ;
  }

>In fact, I wonder if Microsoft might pick up something like this; even
>putting everything into a namespace? Goes hand-in-hand with serious support
>for C++...

I wish. If I were in charge of their headers, I think I'd do:

  WINBASEAPI DWORD WINAPI GetFileAttributesA(IN LPCSTR lpFileName);
  WINBASEAPI DWORD WINAPI GetFileAttributesW(IN LPCWSTR lpFileName);

  #if !defined(__cplusplus) || defined(USE_C_MACROS_NOT_INLINE)
  # ifdef UNICODE
  # define GetFileAttributes GetFileAttributesW
  # else
  # define GetFileAttributes GetFileAttributesA
  # endif // !UNICODE
  #else
    inline DWORD GetFileAttributes(char const* FileName)
    {
      return GetFileAttributesA(FileName) ;
    }
    inline DWORD GetFileAttributes(wchar_t const* FileName)
    {
      return GetFileAttributesW(FileName) ;
    }
  #endif // defined(__cplusplus) && !defined(USE_C_MACROS_NOT_INLINE)

thereby leaving the C guys as they were, but leaving C++ users with the
great advantage of being able to use the inline versions with their
overloading.

And yes, namespaces would be cute:

  #if !defined(__cplusplus) || defined(USE_C_MACROS_NOT_INLINE)
      WINBASEAPI DWORD WINAPI GetFileAttributesA(IN LPCSTR lpFileName);
      WINBASEAPI DWORD WINAPI GetFileAttributesW(IN LPCWSTR lpFileName);
  # ifdef UNICODE
  # define GetFileAttributes GetFileAttributesW
  # else
  # define GetFileAttributes GetFileAttributesA
  # endif // !UNICODE
  #else
  namespace Win32 {
    inline DWORD GetFileAttributesA(char const* FileName)
    {
      extern WINBASEAPI DWORD WINAPI GetFileAttributesA(LPCSTR); //???
      return ::GetFileAttributesA(FileName) ;
    }
    inline DWORD GetFileAttributesW(wchar_t const* FileName)
    {
      extern WINBASEAPI DWORD WINAPI GetFileAttributesW(LPCWSTR);
      return ::GetFileAttributesW(FileName) ;
    }
    inline DWORD GetFileAttributes(char const* FileName)
    {
      return GetFileAttributesA(FileName) ;
    }
    inline DWORD GetFileAttributes(wchar_t const* FileName)
    {
      return GetFileAttributesW(FileName) ;
    }
  } // namespace Win32 {
  #endif // defined(__cplusplus) && !defined(USE_C_MACROS_NOT_INLINE)

which would have the advantage of removing the explicit A/W identifiers
from the global namespace while still linking correctly to the external
functions (I think - the above is untested - how _do_ you locally
declare a global namespace function while within a function in an inner
namespace?).


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk