Pragma en definir macro

99

¿Hay alguna forma de incrustar la declaración pragma en macro con otras declaraciones?

Estoy tratando de lograr algo como:

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

Estoy de acuerdo con las soluciones de refuerzo (excepto para la ola) si existe.

Anycorn
fuente
5
Podría decirse que no lo es: los #pragmas no están definidos ni por los estándares C ni por C ++.
El preprocesador lo es, incluso si el subcomando permitido específico que quiere ejecutar no lo es.
Puppy
@DeadMG: Hay muchas cosas que son comunes entre C y C ++. Si bien el preprocesamiento es en su mayoría común, existen grandes diferencias en cómo se especifica el preprocesamiento según el estándar de lenguaje que se utilice (C89, C99, C ++ y C ++ 0x FCD).
James McNellis
2
@James McNellis: El hecho de que, técnicamente, la mayoría de los programas en C sean portables a C ++, no hace que esa funcionalidad sea realmente común, ya que ningún programador de C ++ haría la gran mayoría. En realidad, los dos idiomas no tienen mucho en común.
Puppy

Respuestas:

115

Si está usando c99 o c ++ 0x, existe el operador pragma, usado como

_Pragma("argument")

que es equivalente a

#pragma argument

excepto que se puede usar en macros (ver sección 6.10.9 del estándar c99, o 16.9 del borrador final del comité c ++ 0x)

Por ejemplo,

#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);

cuando se pone en gcc -Eda

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;
Scott Gales
fuente
32
Como un FYI: MSVC tiene el __pragma()operador de preprocesador, que desafortunadamente es ligeramente diferente del _Pragma()operador de C99 (C99 toma un literal de cadena, MSVC toma tokens que no están en una cadena): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Michael Burr
15
@MichaelBurr MSVC siempre tiene que ser diferente, ¿no?
Thomas
5

Una cosa buena que puede hacer con _Pragma ("argumento") es usarlo para solucionar algunos problemas del compilador, como

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
John Thomas
fuente
0

No, no existe una forma portátil de hacerlo. Por otra parte, no hay formas portátiles de usar #pragma en absoluto. Debido a esto, muchos compiladores de C / C ++ definen sus propios métodos para hacer cosas similares a pragma y, a menudo, se pueden incrustar en macros, pero necesita una definición de macro diferente en cada compilador. Si está dispuesto a seguir ese camino, a menudo termina haciendo cosas como esta:

#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;    

En caso de que no sea obvio, desea definir Weak_by Weak_ecomo construcciones entre corchetes de principio y fin porque algunos compiladores como GCC agregan los atributos como un apéndice a una firma de tipo, y algunos, como MSC, lo agregan como prefijo (o al menos lo hizo una vez, han pasado años desde que utilicé MSC). Tener construcciones entre corchetes le permite definir algo que siempre funciona, incluso si tiene que pasar la firma de tipo completa a una construcción del compilador.

Por supuesto, si intenta portar esto a un compilador sin los atributos que desea, no puede hacer nada más que dejar que las macros se expandan a cero y esperar que su código aún se ejecute. En caso de pura advertencia u optimización de pragmas, esto es probable. En otros casos, no tanto.

Ah, y sospecho que en realidad necesitaría definir Weak_b y Weak_e como macros que toman parámetros, pero no estaba dispuesto a leer los documentos sobre cómo crear una definición débil solo para este ejemplo. Dejo eso como un ejercicio para el lector.

swestrup
fuente
-3

¿Hay alguna forma de incrustar la declaración pragma en macro con otras declaraciones?

No, no puede poner sentencias de preprocesador en sentencias de preprocesador. Sin embargo, podría ponerlo en una inlinefunción. Sin Cembargo, eso derrota a la etiqueta.

sbi
fuente
1
¿De qué serviría ponerlo en una función en línea? Las directivas de preprocesador se procesan antes que cualquier cosa que pueda reconocer una función.
2
C99 tiene inline, y la mayoría de las principales implementaciones de C89 tienen alguna variación.
Chris Lutz
@Chris Asumiendo que su comentario fue dirigido a mí, su punto es: ¿qué?
@Neil - No, lo siento. Lo estaba dirigiendo a la última oración de @ sbi.
Chris Lutz
1
@Chris: ¡Ah, también inlineotra cosa que C tomó prestada de C ++! :)
sbi