tutorialspoint significado punteros perros meaning dogs array c++ pointers

c++ - significado - Usar calificadores de espacio de nombres globales con puntero a los miembros de datos



punteros c++ (1)

Estoy experimentando un error de compilación al intentar utilizar un puntero al miembro de datos al incluir el calificador de espacio de nombres global en la estructura. Reduje mi código a lo siguiente, que funciona :

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 ahora agrego el calificador de espacio de nombres global a la estructura de bar en el argumento para chuckle :

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

... luego ya no se compila y falla con el siguiente error:

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

Veo este comportamiento en MSVC, Clang y GCC.

He puesto ambos ejemplos en Godbolt:

Preguntas

a) ¿Por qué la adición del calificador de espacio de nombres global hace que la compilación falle?

b) ¿Hay alguna razón para esto en la especificación del lenguaje?


Tema sutil!

El compilador no considera el espacio en blanco adicional, por lo que su código es en realidad:

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

... que, por supuesto, no tiene sentido. Debes desambiguar con paréntesis:

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

... y todo está bien.

Si no está entre paréntesis, @Paula_plus_plus lo cubre con un atributo ficticio, que en realidad puede estar vacío, como @T.C. señala de manera útil:

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

El compilador debe ignorarlo en silencio, pero resuelve el problema para el analizador.