29 votes

Utilisation de qualificatifs d'espace de noms globaux avec pointeur sur les membres de données

Je suis en train de vivre une erreur de compilation lors de la tentative d'utiliser un pointeur vers les données de membre lors de l'inclusion de l'espace de noms global qualificatif sur la struct. J'ai réduit mon code pour la suivante, ce qui fonctionne:

namespace foo {
  using sausage = int;
  struct bar { sausage baz; };
}

auto chuckle(foo::bar barry, ::foo::sausage foo::bar::*paul) {
  return barry.*paul;
}

int main() {
  return chuckle(foo::bar{5}, &foo::bar::baz);
}

Si j'ajoute maintenant l'espace de noms global qualificatif pour l' bar struct dans l'argument d' chuckle:

auto chuckle(foo::bar barry, ::foo::sausage ::foo::bar::*paul) {
                                        //  ^~ added ::
  return barry.*paul;
}

...alors, il n'est plus compile et échoue avec l'erreur suivante:

10 : <source>:10:37: error: 'foo::sausage' is not a class, namespace, or enumeration
 auto chuckle(foo::bar barry, ::foo::sausage ::foo::bar::*paul) {
                                     ^~~~~~~
10 : <source>:10:57: error: expected identifier before '*' token
 auto chuckle(foo::bar barry, ::foo::sausage ::foo::bar::*paul) {
                                                         ^
<source>: In function 'auto chuckle(foo::bar, int*)':
11 : <source>:11:17: error: 'paul' cannot be used as a member pointer, since it is of type 'int*'
   return barry.*paul;
                 ^~~~
<source>: In function 'int main()':
15 : <source>:15:45: error: cannot convert 'foo::sausage foo::bar::* {aka int foo::bar::*}' to 'int*' for argument '2' to 'auto chuckle(foo::bar, int*)'
   return chuckle(foo::bar{5}, &foo::bar::baz);
                                             ^

Je vois ce comportement à l'échelle MSVC, Bruit et de la GCC.

J'ai mis deux exemples sur Godbolt:

Questions

a) Pourquoi l'ajout de l'espace de noms global qualificatif cause de la compilation à l'échec?

b) Est-il une raison à cela dans la spécification du langage?

37voto

Quentin Points 3904

Subtile question!

Le compilateur ne pas envisager un espace, de sorte que votre code est en fait:

auto chuckle(foo::bar barry, ::foo::sausage::foo::bar::*paul)

... ce qui, bien sûr, ne fait pas de sens. Vous avez besoin de lever l'ambiguïté avec des parenthèses:

auto chuckle(foo::bar barry, ::foo::sausage (::foo::bar::*paul))
//                                          ^                 ^

... et tout va bien.

Si vous n'êtes pas dans les parenthèses, @Paula_plus_plus vous a couvert avec un mannequin attribut, ce qui peut être vide comme @T. C. obligeamment remarquer:

auto chuckle(foo::bar barry, ::foo::sausage [[]] ::foo::bar::*paul)
//                                          ^^^^

Le compilateur est nécessaire à l'ignorer en silence, mais il n'résoudre le problème de l'analyseur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X