Как бы вы объяснили эту разницу в указателе на члены базового и производного класса с помощью стандартных кавычек? - PullRequest
7 голосов
/ 16 июня 2019

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::*, но это не является нормативным.

1 Ответ

8 голосов
/ 16 июня 2019

Из абзаца, на который вы ссылаетесь, мой акцент:

Если операнд является квалифицированным идентификатором с именем нестатического или вариантного члена m некоторого класса C с типом T, результат имеет тип «указатель на член» класса C типа T ”и является частным обозначением C::m.

«Некоторый класс C» означает, что он не обязательно должен быть того же класса, который указан квалифицированным идентификатором. В этом случае 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.

...