Использование глобальных классификаторов пространства имен с указателем на элементы данных
У меня возникает ошибка компиляции при попытке использовать указатель для члена данных при включении классификатора пространства имен в структуру. Я сократил свой код до следующего, который работает:
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);
}
Если я теперь добавлю глобальный определитель пространства имен в структуру bar
в аргументе chuckle
:
auto chuckle(foo::bar barry, ::foo::sausage ::foo::bar::*paul) {
// ^~ added ::
return barry.*paul;
}
... то он больше не компилируется и не работает со следующей ошибкой:
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);
^
Я вижу это поведение в MSVC, Clang и GCC.
Я привел оба примера на Godbolt:
Вопросы
a) Почему добавление глобального классификатора пространства имен приводит к сбою компиляции?
b) Есть ли причина для этого в спецификации языка?
Ответы
Ответ 1
Тонкая проблема!
Компилятор не рассматривает лишние пробелы, поэтому ваш код на самом деле:
auto chuckle(foo::bar barry, ::foo::sausage::foo::bar::*paul)
... что, конечно, не имеет смысла. Вам нужно устранить двусмысленность с помощью круглых скобок:
auto chuckle(foo::bar barry, ::foo::sausage (::foo::bar::*paul))
// ^ ^
... и все в порядке.
Если вы не находитесь в круглых скобках, @PaperBirdMaster вы покрыли фиктивный атрибут:
auto chuckle(foo::bar barry, ::foo::sausage [[dummy]] ::foo::bar::*paul)
// ^^^^^^^^^
Компилятор должен игнорировать его молча, но он решает проблему для синтаксического анализатора.