Прагма в определении макроса - PullRequest
89 голосов
/ 13 июня 2010

Есть ли какой-нибудь способ встроить оператор прагмы в макрос с другими операторами?

Я пытаюсь достичь чего-то вроде:

#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type_(int handle);                  \
    void delete_ ## type(int handle);                                                \
    #pragma weak delete_ ## type_ = delete_ ## type

Я в порядке с буст-решениями (за исключением волны), если таковые существуют.

Ответы [ 4 ]

105 голосов
/ 13 июня 2010

Если вы используете c99 или c ++ 0x, есть оператор прагмы, который используется как

_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
 ;
4 голосов
/ 28 февраля 2012

Одна хорошая вещь, которую вы можете сделать с _Pragma («аргумент»), это использовать ее для решения некоторых проблем компилятора, таких как

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
0 голосов
/ 13 июня 2010

Нет, нет портативного способа сделать это.Опять же, нет никаких переносимых способов использовать #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 как макросы, которые принимают параметры, но я не хотел читать документы о том, как создатьслабое определение только для этого примера.Я оставляю это как упражнение для читателя.

0 голосов
/ 13 июня 2010

есть ли способ встраивать оператор прагмы в макрос с другими операторами?

Нет, операторы препроцессора нельзя помещать в операторы препроцессора.Однако вы можете поместить его в функцию inline.Это побеждает тег C.

...