Pragma em definir macro

99

Existe alguma maneira de incorporar a instrução pragma na macro com outras instruções?

Estou tentando alcançar algo como:

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

Aceito soluções de impulso (exceto para onda), se houver.

Anycorn
fonte
5
Discutivelmente, não é nem - #pragmas não são definidos pelos padrões C ou C ++.
O pré-processador é, mesmo que o subcomando permitido específico que ele deseja executar não seja.
Filhote de cachorro de
@DeadMG: Há muitas coisas comuns entre C e C ++. Embora o pré-processamento seja mais comum, há grandes diferenças em como o pré-processamento é especificado, dependendo de qual padrão de linguagem está sendo usado (C89, C99, C ++ e C ++ 0x FCD).
James McNellis
2
@James McNellis: Só porque, tecnicamente, a maioria dos programas C são portáveis ​​para C ++, isso não torna essa funcionalidade genuinamente comum, já que nenhum programador C ++ faria a grande maioria dela. As duas línguas não têm muito em comum.
Filhote de cachorro de

Respostas:

114

Se você estiver usando c99 ou c ++ 0x, há o operador pragma, usado como

_Pragma("argument")

que é equivalente a

#pragma argument

exceto que pode ser usado em macros (consulte a seção 6.10.9 do padrão c99, ou 16.9 do projeto de comitê final c ++ 0x)

Por exemplo,

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

quando colocado em gcc -E

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;
Scott Wales
fonte
32
Como um FYI: MSVC tem o __pragma()operador de pré - processador, que infelizmente é um pouco diferente do _Pragma()operador C99 (C99 leva um literal de string, MSVC leva tokens que não estão em uma string): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Michael Burr
15
@MichaelBurr MSVC sempre tem que ser diferente, não é?
Thomas
5

Uma coisa boa que você pode fazer com _Pragma ("argumento") é usá-lo para lidar com alguns problemas do compilador, como

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

Não, não existe uma maneira portátil de fazer isso. Então, novamente, não há nenhuma maneira portátil de usar #pragma. Por causa disso, muitos compiladores C / C ++ definem seus próprios métodos para fazer coisas do tipo pragma, e eles geralmente podem ser embutidos em macros, mas você precisa de uma definição de macro diferente em cada compilador. Se você está disposto a seguir esse caminho, geralmente acaba fazendo coisas como estas:

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

Caso não seja óbvio que você deseja definir Weak_be Weak_ecomo construções de colchetes de início e fim, porque alguns compiladores como o GCC adicionam os atributos como um adendo a uma assinatura de tipo, e alguns, como o MSC, adicionam-no como um prefixo (ou pelo menos o fizeram uma vez, já faz anos que não uso o MSC). Ter contruções de colchetes permite que você defina algo que sempre funciona, mesmo se você tiver que passar a assinatura de tipo inteira para uma construção de compilador.

Claro, se você tentar portar isso para um compilador sem os atributos desejados, não há nada que você possa fazer a não ser deixar as macros se expandirem e esperar que seu código ainda seja executado. No caso de meramente advertir ou otimizar pragmas, isso é provável. Em outros casos, nem tanto.

Ah, e eu suspeito que você realmente precisa definir Weak_b e Weak_e como macros que usam parâmetros, mas eu não estava disposto a ler a documentação para saber como criar uma definição fraca apenas para este exemplo. Deixo isso como um exercício para o leitor.

Swestrup
fonte
-3

existe alguma maneira de incorporar instrução pragma em macro com outras instruções?

Não, você não pode colocar instruções do pré-processador em instruções do pré-processador. Você poderia, entretanto, colocá-lo em uma inlinefunção. Isso derrota a Ctag, no entanto.

sbi
fonte
1
Qual a vantagem de colocá-lo em uma função embutida? As diretivas do pré-processador são processadas antes de qualquer coisa que possa reconhecer uma função.
2
O C99 tem inline, e a maioria das principais implementações do C89 tem algumas variações.
Chris Lutz
@Chris Supondo que seu comentário foi direcionado a mim - seu ponto é - o quê?
@Neil - Não, desculpe. Eu estava dirigindo na última frase de @sbi.
Chris Lutz
1
@Chris: Ah, então inlineé outra coisa que C pegou emprestado de C ++! :)
sbi