使用全局命名空间限定符和指向数据成员的指针

Rez*_*zie 29 c++ pointers

在结构上包含全局命名空间限定符时,尝试使用指向数据成员指针时遇到编译错误.我已将代码缩减为以下内容,其工作原理如下:

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);
}
Run Code Online (Sandbox Code Playgroud)

如果我现在将全局命名空间限定符添加到bar参数中的结构chuckle:

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

...然后它不再编译并失败并出现以下错误:

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);
                                             ^
Run Code Online (Sandbox Code Playgroud)

我在MSVC,Clang和GCC中看到了这种行为.

我把两个例子放在Godbolt上:

问题

a)为什么添加全局命名空间限定符会导致编译失败?

b)语言规范中是否有理由这样做?

Que*_*tin 37

微妙的问题!

编译器不考虑额外的空格,因此您的代码实际上是:

auto chuckle(foo::bar barry, ::foo::sausage::foo::bar::*paul)
Run Code Online (Sandbox Code Playgroud)

......当然,这没有意义.你需要用括号消除歧义:

auto chuckle(foo::bar barry, ::foo::sausage (::foo::bar::*paul))
//                                          ^                 ^
Run Code Online (Sandbox Code Playgroud)

......一切都很好.

如果你没有括号,那么@Paula_plus_plus会为你提供一个虚拟属性,实际上它可能是空的,因为@TC帮助指出:

auto chuckle(foo::bar barry, ::foo::sausage [[]] ::foo::bar::*paul)
//                                          ^^^^
Run Code Online (Sandbox Code Playgroud)

编译器需要以静默方式忽略它,但它确实解决了解析器的问题.

  • 这是一个好的格式化程序有帮助的情况.clang-formatter删除了空间,从而揭示了这个问题. (2认同)