web-dev-qa-db-fra.com

La macro C++ '##' ne fonctionne pas après l'opérateur '->'

J'ai un objet shared_ptr x, qui a les méthodes get et set comme suit: 

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

Quand j'essaie de définir une macro: 

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

MAC(a)

Cela fonctionne bien, mais quand je le fais: 

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

MAC(a)

cela donne l'erreur de compilation suivante: pasting formed '->a', an invalid preprocessing token

23
250

Le préprocesseur fonctionne sur des "jetons" - aime les noms et les opérateurs.

L'opérateur ## crée un nouveau jeton en collant des pièces plus petites. Dans le premier exemple, set_##type##_value devient set_a_value, qui est un jeton valide.

Dans le deuxième exemple, ->##type##_value deviendrait ->a_value, ce qui représente pas un jeton de préprocesseur valide. Il devrait y avoir deux jetons.

Si vous faites juste la ligne x->type##_value(); cela devrait marcher. Vous obtenez les jetons distincts x, ->, a_value, (, ) et ;.

51
Bo Persson

Ce qui est écrit sur l'étain: ->a n'est pas un seul jeton valide de préprocesseur: c'est deux jetons. Vous n'avez pas besoin de coller ici.

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

L'opérateur de collage de jetons (##) est utilisé pour concaténer deux jetons en un seul jeton valid.

Quand tu écris

x->##type##_value();
  • Le premier jeton traité est x.

  • Le jeton suivant est formé en concaténant le jeton -> avec type, puisque type est a, le résultat de la concaténation est ->a, qui doit être un jeton valide, mais ne le est pas.

Par conséquent, vous obtenez l'erreur: pasting formed '->a', an invalid preprocessing token.

Pour résoudre ce problème, il suffit d'écrire

x->type##_value();

Par ici

  • Le premier jeton analysé est x.

  • Le prochain jeton analysé est ->.

  • Le jeton suivant est formé en concaténant le jeton type (qui devient a) avec le jeton _value. Cela donne a_value, qui est un jeton valide.

  • Le prochain jeton est (.

  • Le prochain jeton est ).

  • Le dernier jeton est ;.

1
cute_ptr