Прагма в определении макроса
Есть ли какой-нибудь способ встроить прагматическое выражение в макрос с другими утверждениями?
Я пытаюсь достичь чего-то вроде:
#define DEFINE_DELETE_OBJECT(type) \
void delete_ ## type_(int handle); \
void delete_ ## type(int handle); \
#pragma weak delete_ ## type_ = delete_ ## type
Я в порядке с буст-решениями (за исключением волны), если таковые существуют.
4 ответа
Если вы используете c99 или C++0x, есть оператор pragma, используемый как
_Pragma("argument")
что эквивалентно
#pragma argument
за исключением того, что его можно использовать в макросах (см. раздел 6.10.9 стандарта c99 или 16.9 проекта окончательного комитета C++0x)
Например,
#define STRINGIFY(a) #a
#define DEFINE_DELETE_OBJECT(type) \
void delete_ ## type ## _(int handle); \
void delete_ ## type(int handle); \
_Pragma( STRINGIFY( weak delete_ ## type ## _ = delete_ ## type) )
DEFINE_DELETE_OBJECT(foo);
когда положить в gcc -E
дает
void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
;
Одна хорошая вещь, которую вы можете сделать с _Pragma("аргумент"), это использовать ее для решения некоторых проблем компилятора, таких как
#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
Нет, нет портативного способа сделать это. Опять же, нет никаких переносимых способов использовать #pragma вообще. Из-за этого многие компиляторы C/C++ определяют свои собственные методы для выполнения прагма-подобных вещей, и они часто могут быть встроены в макросы, но вам нужно другое определение макроса для каждого компилятора. Если вы хотите пойти по этому пути, вам часто приходится делать такие вещи:
#if defined(COMPILER_GCC)
#define Weak_b
#define Weak_e __attribute__((weak))
#elif defined(COMPILER_FOO)
#define Weak_b __Is_Weak
#define Weak_e
#endif
#define DEFINE_DELETE_OBJECT(type) \
Weak_b void delete_ ## type_(int handle) Weak_e; \
Weak_b void delete_ ## type(int handle) Weak_e;
Если это не очевидно, вы хотите определить Weak_b
а также Weak_e
как начальные и конечные скобки, потому что некоторые компиляторы, такие как GCC, добавляют атрибуты в качестве дополнения к сигнатуре типа, а некоторые, например MSC, добавляют его в качестве префикса (или, по крайней мере, один раз, это было годами с тех пор, как я использовал) MSC). Наличие контрактов в квадратных скобках позволяет вам определять то, что всегда работает, даже если вам нужно передать всю сигнатуру типа в конструкцию компилятора.
Конечно, если вы попытаетесь перенести это на компилятор без нужных вам атрибутов, вы ничего не сможете сделать, кроме как оставить макросы развернутыми до нуля и надеяться, что ваш код все еще работает. В случае чисто предупреждения или оптимизации прагм, это вполне вероятно. В других случаях не так много.
О, и я подозреваю, что вам действительно нужно определить Weak_b и Weak_e как макросы, которые принимают параметры, но я не хотел читать документы о том, как создать слабое определение только для этого примера. Я оставляю это как упражнение для читателя.
Есть ли способ встроить прагма в макрос с другими заявлениями?
Нет, вы не можете помещать операторы препроцессора в операторы препроцессора. Вы могли бы, однако, положить его в inline
функция. Это побеждает C
тег, хотя.