|
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