我相信这是 clang++ 中与访问类的公共成员函数有关的错误
Posted
技术标签:
【中文标题】我相信这是 clang++ 中与访问类的公共成员函数有关的错误【英文标题】:I believe this is a bug in clang++ related to the access to a class's public member function 【发布时间】:2017-11-12 11:46:33 【问题描述】:以下doesn't compile在clang中:
#include <iostream>
void f() std::cout << "f()\n";
struct S
typedef void(*p)();
operator p() return f;
;
int main()
S s;
s.operator p()();
产量:
main.cpp:13:16: error: unknown type name 'p'; did you mean 'S::p'? s.operator p()(); ^ S::p main.cpp:6:19: note: 'S::p' declared here typedef void(*p)(); ^
但它应该,因为表达式s.operator p()()
访问对象S::s
的公共成员函数。我错过了什么吗?
如果我错了,我会感谢标准的引用来支持答案。
【问题讨论】:
你的链接说明了一切:“你的意思是'S::p'吗?” 请将编译器错误粘贴到问题中,不要只是链接到它们。 转换运算符的名称查找使用类型匹配而不是词法(字符)匹配。即使您说s.operator decltype(&f)()()
,查找也会成功
这个代码看起来格式正确,因为规范说“如果 id-expression 是一个转换函数 ID,它的转换类型 ID 首先在对象的类中查找表达式和名称,如果找到,则使用。”。所以这真的闻起来像clang中的错误......
这里的问题是p
是否应该首先在类范围内查找。 gcc 和 clang 不同。
【参考方案1】:
这似乎是 Clang 中的一个错误。我相信代码是正确的。
Clang 4.0.0 报告:
<source>:13:16: error: unknown type name 'p'; did you mean 'S::p'?
s.operator p()();
^
但是,从 C++14 3.4.5/7 [basic.lookup.clas-s-ref]
如果id-expression是一个conversion-function-id,它的conversion-type-id首先在类中查找 对象表达式和名称(如果找到)将被使用。否则在整个上下文中查找 后缀表达式。在这些查找中的每一个中,只有表示其特化的类型或模板的名称 是否考虑了类型。
[示例:
struct A ; namespace N struct A void g() template <class T> operator T(); ; int main() N::A a; a.operator A(); // calls N::A::operator N::A
—结束示例]
在您的示例中,类型 p
应该已经在类中找到而无需限定。
【讨论】:
经过进一步分析,我想我并没有真正理解[basic.lookup.clas-s-ref]/7中Otherwise it is looked up in the context of the entire postfix-expression
这句话的原因。请注意,here 显示的示例无法编译。你能举个例子说明上面的句子有什么用处吗?
在该示例中,类型名称A
在N::A
的上下文中被正确查找,给出了注入类名称,这意味着N::A
。您在访问的对象中没有任何此类运算符的事实是一个单独的错误。
这里是一个例子,类类型范围内的名字查找失败,但整个后缀表达式范围内的名字查找成功:coliru.stacked-crooked.com/a/8fa9ae6e5f261edc在调用b.operator A();
中,有在N::B
的范围内没有名字A
,但是在调用函数M::f
的范围内可以找到M::A
。
@aschepler 感谢您的评论。我终于得出结论,链接中的示例显示了在整个后缀表达式范围内使用名称查找。以上是关于我相信这是 clang++ 中与访问类的公共成员函数有关的错误的主要内容,如果未能解决你的问题,请参考以下文章