Есть ли в заголовках Windows параметр, который запрещает определение макросов имен нейтральных функций TCHAR? - PullRequest
0 голосов
/ 09 января 2011

Допустим, я реализую простую оболочку вокруг ExpandEnvironmentStringsW :

// ExpandNStuff.hpp:

#include <string>
namespace WindowsApi
{
    std::wstring ExpandEnvironmentStrings(const std::wstring& source);
}

// ExpandNStuff.cpp:

#include <windows.h>
#include "ExpandNStuff.hpp"
#include "Win32Exception.hpp"
namespace WindowsApi
{
    std::wstring ExpandEnvironmentStrings(const std::wstring& source)
    {
        DWORD len;
        std::wstring result;
        len = ::ExpandEnvironmentStringsW(source.c_str(), 0, 0);
        if (len == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }
        result.resize(len);
        len = ::ExpandEnvironmentStringsW(source.c_str(), &result[0], len);
        if (len == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }
        result.pop_back(); //Get rid of extra null
        return result;
    }
}

Ничего страшного - все имеет смысл до этого момента.Посмотрите, что произойдет, когда я добавлю main.cpp:

#include <iostream>
#include <string>
#include "ExpandNStuff.hpp"

int main()
{
    std::wstring source(L"Hello World! Windows is in %WINDIR%");
    std::wstring expanded(WindowsApi::ExpandEnvironmentStrings(source));
    std::wcout << expanded << std::endl;
}

Сюрприз!Этот код не будет ссылаться.Причина в том, что в модуле перевода ExpandNStuff.cpp заголовок windows.h определил ExpandEnvironmentStrings как ExpandEnvironmentStringsW, используя макрос, несмотря на тот факт, что мы попытались сделать нашу реализацию отличной, поместив ее в пространство имен.Поэтому модуль перевода ExpandNStuff.cpp считает, что функция называется WindowsApi::ExpandEnvironmentStringsW, а не WindowsApi::ExpandEnvironmentStrings, как ожидает автор.Но блок перевода main.cpp не #include <windows.h>, поэтому его имя не совпадает с именем в блоке перевода ExpandNStuff.cpp.

Исправление заключается в добавлении этого в ExpandNStuff.hpp:

#ifdef ExpandEnvironmentStrings
#undef ExpandEnvironmentStrings
#endif

Однако выполнение этого для каждого API может быть утомительным.Я бы просто был вынужден вызывать версию функции "W" или "A" явно, чем быть укушенным #define ошибками вроде этой.Есть ли способ отключить макросы?

Ответы [ 2 ]

3 голосов
/ 09 января 2011

Их определения не заключены ни в один макрос.

WINBASEAPI
BOOL
WINAPI
GetVolumeInformationA(
    __in_opt  LPCSTR lpRootPathName,
    __out_ecount_opt(nVolumeNameSize) LPSTR lpVolumeNameBuffer,
    __in      DWORD nVolumeNameSize,
    __out_opt LPDWORD lpVolumeSerialNumber,
    __out_opt LPDWORD lpMaximumComponentLength,
    __out_opt LPDWORD lpFileSystemFlags,
    __out_ecount_opt(nFileSystemNameSize) LPSTR lpFileSystemNameBuffer,
    __in      DWORD nFileSystemNameSize
    );
WINBASEAPI
BOOL
WINAPI
GetVolumeInformationW(
    __in_opt  LPCWSTR lpRootPathName,
    __out_ecount_opt(nVolumeNameSize) LPWSTR lpVolumeNameBuffer,
    __in      DWORD nVolumeNameSize,
    __out_opt LPDWORD lpVolumeSerialNumber,
    __out_opt LPDWORD lpMaximumComponentLength,
    __out_opt LPDWORD lpFileSystemFlags,
    __out_ecount_opt(nFileSystemNameSize) LPWSTR lpFileSystemNameBuffer,
    __in      DWORD nFileSystemNameSize
    );
#ifdef UNICODE
#define GetVolumeInformation  GetVolumeInformationW
#else
#define GetVolumeInformation  GetVolumeInformationA
#endif // !UNICODE

Вы можете видеть, что нет удобного переключателя для предотвращения # определения GetVolumeInformation.

EDIT:

У Boost есть решение - BOOST_PREVENT_MACRO_SUBSTITUTION. Они используют его для min () и max (). "Используйте min BOOST_PREVENT_MACRO_SUBSTITUTION (a, b); чтобы сделать зависимый от аргумента вызов min (a, b).".

1 голос
/ 09 января 2011

Эти десятки тысяч макросов в заголовке Windows определенно раздражают.Лучшее, что я мог придумать до сих пор, это

  1. строго ограничить, включая <windows.h>
  2. пунктуально не определять все, что появляется:

Но # 2 - последнее средство, гораздо больше можно достичь, строго придерживаясь # 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...