Обработка макро-переопределения, не изменяя.h файлы … C / язык C++

Фон:

Позвольте предполагают, что у меня есть два заголовочных файла a.h и b.h.

a.h содержит:

#define VAR 1

b.h содержит:

#define VAR 2

Примечание: Название обоих из макроса - то же. Позвольте говорят, что у меня есть некоторый файл myFile.c, который включает оба из заголовочных файлов т.е. a.h и b.h.

Когда я пытаюсь получить доступ к VAR, я получаю ошибку переопределения VAR.

Для разрешения этой проблемы я вставил #ifndef оператор VAR и в a.h и в b.h файлы для предотвращения этой ошибки. файл a.h становится

#ifndef VAR
  #define VAR 1
#endif

файл b.h становится

#ifndef VAR
  #define VAR 2
#endif

Примечание: Заголовочный файл может содержать несколько макросы, не всего один макрос.

Проблема:

Давайте предположим, что a.h и b.h файлы получены из сторонней библиотеки. Эти файлы не содержат #ifndef оператор VAR.

Мне не разрешают изменить их заголовочные файлы.

Я могу разрешить макро-ошибку переопределения 'VAR' в myFile.c или myFile.cpp файле, который использует макрос VAR?

Я знаю меня, #undef VAR может использоваться для неопределения макро-VAR. Как я могу выборочно включать VAR позже в мою программу? т.е. на строке, которую кодируют 10 из myFile.c, я должен смочь обратиться к определению VAR из a.h файла, на строке 15 из моего кода я должен смочь обратиться к VAR из b.h файла, и на строке 18 снова я должен смочь обратиться к VAR из a.h файла.

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

Я думал об использовании приема пространства имен для решения вопроса. Определите первый заголовочный файл в пространстве имен первый и второй заголовочный файл во втором пространстве имен.

Я пытался определить два пространства имен. Первое пространство имен содержит #include a.h, и второе пространство имен содержит b.h. Однако прием пространства имен не работает с макросом. Когда я пытался получить доступ к firstns:: VAR, компилятор сообщает о сообщении об ошибке.

Можно ли предложить некоторый путь?

6
задан Georg Fritzsche 6 April 2010 в 14:47
поделиться

3 ответа

Вы можете всегда включать проблемные файлы заголовков через свой собственный выделенный заголовок. файлы, в которые можно добавить необходимые макросы #ifdef , #undef и т. д. для предотвращения ошибок переопределения. Например.

wrapperToA.h
-----
#ifdef VAR
  #undef VAR
#endif

#include "a.h"

Обновление: @Vlad тем временем разработал полное решение - слава ему (и +1: -)

4
ответ дан 9 December 2019 в 20:41
поделиться

Продолжить ответ Питера Торока.

Обычно рекомендуется оборачивать сторонние компоненты.

Есть несколько шагов:

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

Вас больше интересует первое утверждение, которое также является наиболее распространенным. Просто оберните их:

// wrapper/a.h
#ifdef VAR
#undef VAR
#endif // ifdef VAR

#include <3rdparty/a.h>

Если вы систематически обертываете все свои зависимости таким образом, у вас не возникнет проблем с настройкой впоследствии, поскольку вы можете изменить свои собственные заголовки оболочки и просто перекомпилировать приложение, не вмешиваясь явно в сторонние заголовки (что является НИКОГДА не рекомендуется).

Однако есть вопрос о влиянии, который вы должны внимательно изучить ...

// 3rdparty/a.h
#define VAR 1

// 3rdparty/aa.h
#include "a.h"
typedef int IntArray[VAR];

// 3rdparty2/b.h
#define VAR 2

Это определенно сложнее :) Вам также необходимо заключить "aa.h" в undef , чтобы избежать проблема ...

И, конечно, это означает, что вам лучше не полагаться на VAR самостоятельно где-либо в вашем коде, поскольку вы знаете, что его определение может измениться в зависимости от порядка, в котором вы включаете заголовки .. .

0
ответ дан 9 December 2019 в 20:41
поделиться

Расширение макроса происходит на уровне препроцессора и не зависит от использования пространства имен.

Являются ли все макросы, которые вы хотите использовать, простыми константами, не используемыми в конкатенации токенов и т.д.?

Если да, то вы можете попробовать что-то вроде следующего, чтобы преодолеть разрыв между препроцессором и компилятором и сохранить доступ к A и B определениям VAR и т.д., если это подходит для вашей ситуации:

// ab_wrapper.h
#include <a.h>
static const int   A_VAR1 = VAR1;
static const char* A_VAR2 = VAR2;
#undef VAR1
#undef VAR2

#include <b.h>
static const int   B_VAR1 = VAR1;
static const char* B_VAR2 = VAR2;

// code.c
#include <ab_wrapper.h>
...
int x = A_VAR1;
int y = B_VAR1;
...
8
ответ дан 9 December 2019 в 20:41
поделиться