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

时间:2016-10-01 13:39:47

标签: c++ templates

[temp.explicit]包含以下措辞:

  

通常的访问检查规则不适用于用于指定显式实例化的名称。 [注意: In   特别是,函数声明符中使用的模板参数和名称(包括参数类型,   返回类型和异常规范)可以是通常不属于的私有类型或对象   可访问的,模板可以是通常不会的成员模板或成员函数   无障碍。 -end note]

为什么这些规则专门针对此案例禁用?在极端情况下,这允许以明确定义的方式arbitrary access of any private member of any classdemo - 零警告):

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

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

1 个答案:

答案 0 :(得分:1)

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

注意:@Xeo已经在上面的评论中解释了大部分这些要点。