模板专用化中出现受保护成员访问错误

Protected member access error in template specialization

本文关键字:受保护 成员 访问 错误 专用      更新时间:2023-10-16
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;
  }
};

错误消息:

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;
                    ^

我想知道为什么受保护的成员不能在模板专业化中访问。这些代码毫无意义,只是为了测试。

当public从基类继承时,其受保护的成员将成为派生类的"保护成员",可以在派生类的成员函数中访问该成员。请注意,它们只能通过派生类本身(及其派生类(进行访问。但是受保护的成员不能通过基类访问。这就是为什么&safe_bool::this_type_does_not_support_comparisons;有效而&safe_bool_base::this_type_does_not_support_comparisons;无效的原因。

从标准来看,11.4/1受保护的成员访问[受保护类别]:

(强调我的(

除第条前面所述之外的额外访问检查当非静态数据成员或非静态时应用[class.access]成员函数是其命名类的受保护成员([class.access.base](114如前所述,访问受保护的由于引用发生在朋友或成员中,因此授予成员如果访问是为了形成指向成员的指针([expr.unary.op](,嵌套名称说明符应表示C或类派生自C。所有其他访问都涉及(可能是隐式的(对象表达式([expr.ref](。在这种情况下,对象的类表达式应为C或从C派生的类。[示例:

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,基本上与代码的情况相同。顺便说一句,这与模板专业化无关。