Прагма в макросе определения

99

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

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

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

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

Anycorn
источник
5
Возможно, это не так - #pragmas не определены стандартами C или C ++.
Препроцессор работает, даже если конкретная разрешенная подкоманда, которую он хочет запустить, не выполняется.
Puppy
@DeadMG: У C и C ++ есть много общего. Хотя предварительная обработка в основном распространена, существуют серьезные различия в том, как указывается предварительная обработка, в зависимости от того, какой стандарт языка используется (C89, C99, C ++ и C ++ 0x FCD).
Джеймс МакНеллис,
2
@ Джеймс МакНеллис: Просто потому, что технически большинство программ на C переносимо на C ++, не делает этой действительно общей функциональности, поскольку ни один программист на C ++ не будет выполнять подавляющее большинство из них. Между этими двумя языками на самом деле не так много общего.
Puppy

Ответы:

116

Если вы используете 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
 ;
Скотт Уэльс
источник
32
К вашему сведению: MSVC имеет __pragma()оператор препроцессора, который, к сожалению, немного отличается от _Pragma()оператора C99 (C99 принимает строковый литерал, MSVC принимает токены, которых нет в строке): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Майкл Берр,
15
@MichaelBurr MSVC всегда должен быть другим, не так ли?
Thomas
5

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

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
Джон Томас
источник
0

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

swestrup
источник
-3

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

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

SBI
источник
1
Что хорошего в том, чтобы поместить его во встроенную функцию? Директивы препроцессора обрабатываются до того, как все, что может распознать функцию.
2
C99 имеет inline, и большинство основных реализаций C89 имеют некоторые вариации.
Крис Лутц,
@Chris Предполагая, что ваш комментарий был адресован мне - ваша точка зрения - что?
@ Нил - Нет, прости. Я направил это в последнем предложении @ sbi.
Крис Лутц,
1
@Chris: А, это inlineеще одна вещь, которую C позаимствовал из C ++! :)
sbi