Как избежать конфликта имен с макросами, определенными в заголовочных файлах Windows? - PullRequest
15 голосов
/ 24 февраля 2010

У меня есть некоторый код C ++, который включает метод с именем CreateDirectory(). Раньше в коде использовались только STL и Boost, но недавно мне пришлось включить <windows.h>, чтобы я мог искать CSIDL_LOCAL_APPDATA.

Теперь этот код:

filesystem.CreateDirectory(p->Pathname()); // Actually create it...

Больше не компилируется:

error C2039: 'CreateDirectoryA' : is not a member of ...

Что соответствует этому макросу в winbase.h:

#ifdef UNICODE
#define CreateDirectory  CreateDirectoryW
#else
#define CreateDirectory  CreateDirectoryA
#endif // !UNICODE

Препроцессор переопределяет мой вызов метода. Есть ли какой-нибудь возможный способ избежать этого конфликта имен? Или мне нужно переименовать мой CreateDirectory() метод?

Ответы [ 8 ]

14 голосов
/ 24 февраля 2010

Вам будет лучше, если вы просто переименуете свой метод CreateDirectory. Если вам нужно использовать Windows API, борьба с Windows.h - это проигрышная битва.

Кстати, если вы были последовательны в том числе windows.h, это все равно будет компилироваться. (хотя у вас могут быть проблемы в других местах).

9 голосов
/ 24 февраля 2010

Вы можете создать модуль, единственной целью которого является #include <windows.h>, и найти CSIDL_LOCAL_APPDATA, заключенный в функцию.

int get_CSIDL_LOCAL_APPDATA(void)
{
    return CSIDL_LOCAL_APPDATA;
}

Кстати, молодец, что понял, что случилось!

9 голосов
/ 24 февраля 2010

# undef CreateDirectory

1 голос
/ 24 февраля 2010

Как разработчик, работающий над кроссплатформенной кодовой базой, это проблема. Единственный способ справиться с этим -

  • убедитесь, что windows.h - по крайней мере для сборок Windows - включен повсеместно. Затем макрос CreateDirectory определяется в каждом из ваших модулей компиляции и универсально заменяется CreateDirectoryW. Предварительно скомпилированные заголовки идеально подходят для этого

ИЛИ, если это неприятное предложение (и оно для меня)

  • изолирует использование windows.h в файлы утилит, специфичные для windows. Создайте файлы, которые экспортируют основные необходимые функции. Заголовочные файлы должны использовать типы данных, которые совместимы, но НЕ зависят от включения windows.h. Файл реализации cpp должен (очевидно) использовать windows.h.

Если ваши функции utlility должны включать файлы заголовков проекта с конфликтующими символами, тогда необходим следующий шаблон:

#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...

Затем вам нужно будет явно вызвать немакро-версию любых функций Windows API, которые у вас есть # undef'd - CreateDirectoryA или W и т. Д.

0 голосов
/ 13 августа 2018

Вы можете создать резервную копию CreateDirectory, затем отменить ее определение, а затем определить ее снова, когда закончите работу с пользовательской.

#ifdef CreateDirectory
#define CreateDirectory_Backup CreateDirectory
#undef CreateDirectory
#endif

// ...
// Define and use your own CreateDirectory() here.
// ...

#ifdef CreateDirectory_Backup
#define CreateDirectory CreateDirectory_Backup
#undef CreateDirectory_Backup
#endif
0 голосов
/ 10 февраля 2017

Обратите внимание, что конфликт имен обычно происходит из-за включения определенного заголовочного файла. До этого момента такие вещи, как CreateDirectory и GetMessage не включались в видимость, и код компилировался без проблем.

Вы можете выделить такое включение в заголовочный файл оболочки и "#undef what" в конце. Тогда любое имя, которое у вас есть, исчезнет. Если, конечно, вам не нужно использовать эти макросы в вашем собственном коде (да, так что очень вероятно ...)

0 голосов
/ 14 января 2017

push макрос, undef это и pop макрос снова:

#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
 // ...
}
#pragma pop_macro("CreateDirectory")
0 голосов
/ 24 февраля 2010
#pragma push_macro("CreateDirectory")

Если ничего не работает, вместо переименования вы можете использовать собственное пространство имен для своих функций.

...