模板特化中受保护的成员访问错误

时间:2016-07-29 10:42:09

标签: c++ templates inheritance template-specialization safe-bool-idiom

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

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

1 个答案:

答案 0 :(得分:1)

当公共从基类继承时,其受保护的成员将成为派生类&#39;保护成员,可以在派生类中访问&#39;成员职能。请注意,它们只能通过派生类本身(及其派生类)进行访问。但是不能通过基类访问受保护的成员。这就是为什么&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]

开始

(强调我的)

  

除了前面条款中描述的那些之外的附加访问检查   [class.access]在非静态数据成员或非静态时应用   member function是其命名类的受保护成员   ([class.access.base])114如前所述,访问受保护的   成员被授予,因为引用发生在朋友或成员中   一些C类。如果访问是形成指向成员的指针   ([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,基本上与代码的情况相同。顺便说一句,它与模板专业化无关。