ti-enxame.com

Macro C++ '##' não funciona depois do operador '->'

Eu tenho um objeto shared_ptr x, que tem métodos get e set da seguinte maneira: 

x->a_value();
x->set_a_value();
x->b_value();
x->set_b_value();

Quando tento definir uma macro: 

#define MAC(type) \
  x->set_##type##_value(val);

MAC(a)

Funciona bem, mas quando eu faço: 

#define MAC(type) \
  x->##type##_value();

MAC(a)

ele dá o seguinte erro de compilação: pasting formed '->a', an invalid preprocessing token

23
250

O pré-processador funciona em "tokens" - gosta de nomes e operadores.

O operador ## cria um novo token colando partes menores juntas. No primeiro exemplo, set_##type##_value torna-se set_a_value, que é um token válido.

No segundo exemplo, ->##type##_value se tornaria ->a_value, que é not um token de pré-processador válido. Deve ser dois tokens.

Se você acabou de fazer a linha x->type##_value(); ele deve funcionar. Você obtém os tokens separados x, ->, a_value, (, ) e ;.

51
Bo Persson

O que está escrito na lata: ->a não é um token único e válido do pré-processador: são dois tokens. Você não precisa colar aqui.

#define MAC(type) \
  x->type##_value();
16
Quentin

O operador de colagem de tokens (##) é usado para concatenar dois tokens em um único válido token.

Quando você escreve

x->##type##_value();
  • O primeiro token processado é x.

  • O próximo token é formado pela concatenação do token -> com type, já que type é a, o resultado da concatenação é ->a, que deve ser um token válido, mas não é.

Portanto, você obtém o erro: pasting formed '->a', an invalid preprocessing token.

Para consertar isso, apenas escreva

x->type##_value();

Deste jeito

  • O primeiro token analisado é x.

  • O próximo token analisado é ->.

  • O próximo token é formado pela concatenação do token type (que se torna a) com o token _value. Isso dá a_value, que é um token válido.

  • O próximo token é (.

  • O próximo token é ).

  • O último token é ;.

1
cute_ptr