Прагма у визначенні макросу


99

Чи є якийсь спосіб вбудувати висловлювання прагми в макро з іншими твердженнями?

Я намагаюся досягти чогось типу:

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

Я добре з розширювальними рішеннями (крім хвилі), якщо такі існують.


5
Можливо, це не є ні - #прагми не визначені ні стандартами С, ні С ++.

Препроцесор є, навіть якщо конкретна дозволена підкоманда, яку він хоче запустити, не є.
Щеня

@DeadMG: Є дуже багато речей, які є спільними між C і C ++. Хоча попередня обробка в основному поширена, існують великі відмінності в тому, як задається попередня обробка залежно від того, який стандарт мови використовується (C89, C99, C ++ та C ++ 0x FCD).
Джеймс McNellis

2
@James McNellis: Тільки тому, що технічно більшість програм C переносяться на C ++, це не робить справді загальноприйнятою функціональністю, оскільки жоден програміст на C ++ не зробив би переважну більшість із них. Дві мови насправді не мають багато спільного.
Щеня

Відповіді:


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
Як FYI: MSVC має __pragma()оператора препроцесора, який, на жаль, трохи відрізняється від _Pragma()оператора C99 (C99 приймає рядковий літерал, MSVC приймає маркери, які не є в рядку): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Майкл Берр

15
@MichaelBurr MSVC завжди має бути іншим, чи не так?
Томас

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 як макроси, які приймають параметри, але я не хотів читати документи, як створити слабке визначення саме для цього прикладу. Я залишаю це як вправу для читача.


-3

чи є якийсь спосіб вбудувати висловлювання прагми в макро з іншими твердженнями?

Ні, ви не можете розміщувати оператори препроцесора в операторах препроцесора. Ти можеш, однак, поставити його у inlineфункцію. Це C, однак, перемагає тег.


1
Яке б користь від того, щоб зробити це вбудованою функцією? Передпроцесорні директиви обробляються перед тим, що може розпізнати функцію.

2
C99 має inline, і більшість основних реалізацій C89 мають певні зміни.
Кріс Лутц

@Chris Припустимо, що ваш коментар був спрямований на мене - ваша думка - що?

@Neil - Ні, вибач. Я скеровував це в останньому реченні @ sbi.
Кріс Луц

1
@Chris: А, inlineце ще одна річ, яку C запозичив у C ++! :)
sbi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.