【问题标题】:Using global namespace qualifiers with pointer to data members使用带有指向数据成员的指针的全局命名空间限定符
【发布时间】:2017-11-20 13:59:00
【问题描述】:

当我在结构中包含全局命名空间限定符时尝试使用pointer to data member 时遇到编译错误。我已将代码简化为以下,有效

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) 语言规范中有此原因吗?

【问题讨论】:

  • 我怎么错过了这个问题!这么多巴里......

标签: c++ pointers


【解决方案1】:

微妙的问题!

编译器不考虑额外的空格,所以你的代码实际上是:

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

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

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

...一切都很好。

如果您不喜欢括号,@Paula_plus_plus 是否为您覆盖了一个虚拟属性,正如@T.C. 有用地指出的那样,它实际上可以是空的:

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

编译器需要默默地忽略它,但它确实为解析器解决了问题。

【讨论】:

  • 这是一个好的格式化程序提供帮助的情况。 clang-formatter 删除了空格,从而揭示了问题。
  • @Quentin:是的,这可以解决问题。我没有考虑过它与函数指针共享语法。这样看,我现在可以看到模棱两可了。谢谢! :)
  • 它是否也适用于虚拟属性? auto chuckle(foo::bar barry, ::foo::sausage [[dummy]] ::foo::bar::*paul)
  • @PaperBirdMaster 太可怕了,它确实有效!我可以将它包含在答案中吗?
  • @Quentin 只要您对它感到满意(即使它很糟糕),请将其包含在答案中;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 2018-10-09
  • 1970-01-01
  • 2014-09-24
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多