Ответ 1
Вы не вызываете get
из a
! Фактически, то, что получает возврат, является указателем класса на член внутри a
, а тип его - int A::*
, поэтому для доступа к этому значению требуется экземпляр a
.
Например, позвольте мне немного поиграть с вашим кодом:
struct A {
A(int a):a(a) { }
int b;
private:
int a;
};
void test() {
auto p = &A::b;
std::cout << a.*p << std::endl;
}
Я звонил p
изнутри a
? a
не имеет p
, это именно то, что произошло в вашем коде, get
function return &A::a
, и вы используете a
, чтобы прочитать его значение! что все, ничего не так, и я думаю, что он будет скомпилирован во всех компиляторах.
Еще один вопрос: почему С++ разрешает объявление шаблона с использованием частного члена a
. Стандарт С++ говорит:
14.7.2p8. Обычные правила проверки доступа не применяются к именам, используемым для указания явных экземпляров. [Примечание: в частности, шаблон аргументы и имена, используемые в деклараторе функции (включая типы параметров, типы возвращаемых данных и спецификации исключений) могут быть частные типы или объекты, которые обычно не будут доступны и шаблон может быть шаблоном-членом или функцией-членом, которая обычно не доступны.]
Но если вы попытаетесь создать экземпляр или даже typedef
указанный шаблон, вы получите сообщение об ошибке.
Немного измените свой пример:
struct A {
private:
int a;
friend void f();
};
// Explicit instantiation - OK, no access checks
template struct Rob<A_f, &A::a>;
// Try to use the type in some way - get an error.
struct Rob<A_f, &A::a> r; // error
typedef struct Rob<A_f, &A::a> R; // error
void g(struct Rob<A_f, &A::a>); // error
// However, it Ok inside a friend function.
void f() {
Rob<A_f, &A::a> r; // OK
typedef Rob<A_f, &A::a> R; // OK
}