demo:
#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';
}
代码打印
decltype(&B::i) == int A::* ? true
10
decltype(&B::i) == int B::* ? false
10
我在[expr.unary.op]/3中使用了示例,其中标准指出&B::i
的类型为int A::*
,但这不是规范性的。
答案 0 :(得分:8)
在您链接的段落中,重点是我的:
如果操作数是命名非静态或变体成员的合格ID
m
某类C
的类型T
,结果的类型为“指向成员的指针 类型为C
的类T
的名称,并且是表示C::m
的prvalue。
“某些类C
”意味着它不必与qualified-id所提及的类相同。在这种情况下,i
是A
的成员,并且即使被A
命名也仍然是&B::i
的成员。因此,&B::i
的类型为int A::*
,您可以通过测试进行验证
std::is_same<decltype(&B::i), int A::*>::value
根据[class.qual]/1,成员查找遵循[class.member.lookup]中详述的算法。根据那里的规则检查成员i
的子对象,确定类C
。由于i
是子对象A
的成员,因此将指向该成员的指针的类确定为A
。