1
class safe_bool_base { 
protected: 
    void this_type_does_not_support_comparisons() const {} 
}; 

template <typename T=void> class safe_bool : public safe_bool_base { 
public: 
    void func() { 
    &safe_bool::this_type_does_not_support_comparisons; 
    &safe_bool_base::this_type_does_not_support_comparisons; 
    } 
}; 

template<> class safe_bool<void> : public safe_bool_base { 
public: 
    void func() { 
    &safe_bool::this_type_does_not_support_comparisons; 
    &safe_bool_base::this_type_does_not_support_comparisons; 
    } 
}; 

Сообщения об ошибке:Protected ошибки доступа члена в специализации шаблона

zzz.cpp: In member function 'void safe_bool<void>::func()': 
zzz.cpp:7:10: error: 'void safe_bool_base::this_type_does_not_support_comparison 
s() const' is protected 
void this_type_does_not_support_comparisons() const {} 
    ^
zzz.cpp:22:24: error: within this context 
    &safe_bool_base::this_type_does_not_support_comparisons; 
        ^

Интересно, почему защищенный член не может быть посещен в специализации шаблона. Коды не имеют смысла и просто для тестирования.

+1

На самом деле 'safe_bool_base :: this_type_does_not_support_comparisons()' работает хорошо, но '& safe_bool_base :: this_type_does_not_support_comparisons' (с адресом функции) этого не делает. Поэтому я хочу выяснить проблему. – immiao

ответ

1

Когда public inherit от базового класса, его защищенные члены становятся защищенными членами производного класса, к которым можно получить доступ в функциях-членах производного класса. Обратите внимание, что они доступны только через сам производный класс (и его производные классы). Но защищенные члены не могут быть доступны через базовый класс. Вот почему &safe_bool::this_type_does_not_support_comparisons; работает, но &safe_bool_base::this_type_does_not_support_comparisons; нет.

От стандарта, $11.4/1 Protected member access [class.protected]:

(emphasie шахта)

Дополнительные проверки доступа помимо тех, которые описаны ранее в пункте [class.access] применяется, когда не-статический член данных или non-static Функция-член является защищенным членом своего класса именования ([class.access.base]) 114 Как описано ранее, доступ к защищенному участнику предоставляется, поскольку ссылка встречается у друга или члена какого-либо класса C. Если доступ заключается в формировании указателя на член ([expr.unary.op]), спецификатор вложенных имен должен обозначать C или класс , полученный из C.. Все другие обращения включают (возможно, неявный) выражение объекта ([expr.ref]). В этом случае класс выражения объекта должны представлять собой С или класс, полученный из С. [Пример:

class B { 
protected: 
    int i; 
    static int j; 
}; 

class D1 : public B { 
}; 

class D2 : public B { 
    friend void fr(B*,D1*,D2*); 
    void mem(B*,D1*); 
}; 

... 
void D2::mem(B* pb, D1* p1) { 
    pb->i = 1;     // ill-formed 
    p1->i = 2;     // ill-formed 
    i = 3;      // OK (access through this) 
    B::i = 4;      // OK (access through this, qualification ignored) 
    int B::* pmi_B = &B::i;  // ill-formed 
    int B::* pmi_B2 = &D2::i;  // OK 
    j = 5;      // OK (because j refers to static member) 
    B::j = 6;      // OK (because B::j refers to static member) 
} 

... 

- конец пример]

Примечание утверждение int B::* pmi_B = &B::i; // ill-formed в примере кода из стандарт, в основном это тот же самый код вашего кода. Кстати, это не имеет никакого отношения к специализации шаблонов.

+0

Ну, компилятор не сообщает об ошибке в объявлении шаблона, но специализации. Это заставило меня задуматься о типовой специализации. Спасибо за подробное объяснение! – immiao

Смежные вопросы