为什么显式模板实例化存在访问检查漏洞

Why does a hole for access checking exist for explicit template instantiations?

本文关键字:存在 访问 检查 漏洞 实例化 为什么      更新时间:2023-10-16

〔temp.explicit〕包含以下语句:

通常的访问检查规则不适用于用于指定显式实例化的名称[注:In特别是在函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常规范(可能是私有类型或对象,而通常不会可访问,并且该模板可能是成员模板或成员函数,而通常不会可访问--尾注]

为什么这些规则是专门针对这种情况禁用的?在极端情况下,这允许以定义良好的方式任意访问任何类的任何私人成员(演示-零警告(:

struct A {
private:
  int member;
};
template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};
// tag used to access A::member
struct A_member { 
  typedef int A::*type;
  friend type get(A_member);
};
template struct Rob<A_member, &A::member>;
int main() {
  A a;
  a.*get(A_member()) = 42; // write 42 to it
  std::cout << "proof: " << a.*get(A_member()) << std::endl;
}

这就是这个规则的缺点。有什么好处?为什么我们需要这个洞来避免访问检查?

Herb Sutter的GotW#76涵盖了这个问题。成员函数应该能够访问类的私有成员。当成员函数是一个模板时,您希望能够专门化这样的模板。这是C++访问控制模型和模板模型之间的冲突,可以通过使(已经很复杂的(C++标准复杂化来避免这种冲突。虽然可以通过这种方式绕过C++访问控制并访问私人成员,但强烈建议您不要这样做。

注意:@Xeo已经在上面的评论中解释了其中的大部分