c++ - 模板特化中的 protected 成员访问错误

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

我想知道为什么在模板特化中不能访问 protected 成员。代码无意义,仅供测试。

最佳答案

当public继承自基类时,它的protected成员成为派生类的protect成员,可以在派生类的成员函数中访问。请注意,它们只能通过派生类本身(及其派生类)访问。但是不能通过基类访问 protected 成员。这就是为什么 &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] :

(强调我的)

An additional access check beyond those described earlier in Clause [class.access] is applied when a non-static data member or non-static member function is a protected member of its naming class ([class.access.base])114 As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member ([expr.unary.op]), the nested-name-specifier shall denote C or a class derived from C. All other accesses involve a (possibly implicit) object expression ([expr.ref]). In this case, the class of the object expression shall be C or a class derived from C. [ Example:

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)
}

...

— end example ]

注意语句 int B::* pmi_B = &B::i;//ill-formed 在标准示例代码中,基本上与您的代码相同。顺便说一句,它与模板特化无关。

关于c++ - 模板特化中的 protected 成员访问错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38656798/

相关文章:

c++ - 您可以通过继承访问 'promote' 规范,您可以访问 'demote' 规范吗?

c++ - 更改构造函数优先级

python - 从 Python 中的嵌套子类访问父变量

c++ - 对 `gnuplot_init()' 的 undefined reference

C++: STRING 函数返回十六进制值而不是字符串

c++ - 将方法的替代实现 (SFINAE) 移动到单独的文件

c++ - 根据表达式的有效性选择要应用的函数

java - 如果需要抽象接口(interface),则不允许在函数参数中提供已实现的接口(interface)

c++ - 将基类的对象传递给派生类的引用函数

c++ - GCC C/C++ 双重行为