Ale*_*der 8 c++ pointer-to-member language-lawyer
演示:
#include<iostream>
struct A { int i = 10; };
struct B : A { };
int main(){
std::cout << "decltype(&B::i) == int A::* ? " << std::boolalpha
<< std::is_same<decltype(&B::i), int A::*>::value << '\n'; //#1
A a;
std::cout << a.*(&A::i) << '\n';
std::cout << "decltype(&B::i) == int B::* ? "
<< std::is_same<decltype(&B::i), int B::*>::value << '\n'; //#2
B b;
std::cout << b.*(&B::i) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
代码打印
decltype(&B::i) == int A::* ? true
10
decltype(&B::i) == int B::* ? false
10
Run Code Online (Sandbox Code Playgroud)
我在[expr.unary.op] / 3中使用了示例,其中标准说的类型&B::i是int A::*,但这不是规范性的。
在您链接到的段落中,请强调:
如果操作数是一个合格的-ID命名非静态或变体构件
m某些类C型T,该结果具有类型“指针类的成员C类型的T”,并且是一个指定prvalueC::m。
“某些类别C”表示它不必与qualified-id提及的类别相同。在这种情况下,即使是由命名,i也是的成员A,并且仍然是的成员。因此,类型为,您可以通过测试进行验证A&B::i&B::iint A::*
std::is_same<decltype(&B::i), int A::*>::value
Run Code Online (Sandbox Code Playgroud)
根据[class.qual] / 1,成员查找遵循[class.member.lookup]中详细介绍的算法。i类别C是根据那里的规则检查成员所来自的子对象的。由于i是子对象的成员,因此A将指向成员的指针的类确定为A。