使用模板技巧访问私有成员 [英] access private member using template trick

查看:222
本文介绍了使用模板技巧访问私有成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从博客文章 访问私人成员:更安全的nastiness Johannes Schaub - litb

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

// use
struct A {
  A(int a):a(a) { }
private:
  int a;
};

// tag used to access A::a
struct A_f { 
  typedef int A::*type;
  friend type get(A_f);
};

template struct Rob<A_f, &A::a>;

int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}

如何 get 可以调用 a 对象,因为它未定义在类A

how get function can be call from a object since its not defined inside class A ?

EDIT:

我不明白为什么get必须有Tag作为参数而不是 a 。* get< A_f>()
=>确定是由于ADL机制

I don't understand why get must have Tag as parameter instead of a.*get<A_f>() => ok it's due to ADL mechanism

推荐答案

p>您不是从 a 调用 get !实际上,get返回是指向 A 中的成员的类指针,类型为 int A :: * 您需要一个 A 的实例来访问该值。

You are not calling get from a! Actually what get return is a class pointer to a member inside A and type of it is int A::* so you need an instance of A to access that value.

例如,让我玩一些代码:

For example let me play a little with your code:

struct A {
    A(int a):a(a) { }
    int b;
private:
    int a;
};
void test() {
    auto p = &A::b;
    std::cout << a.*p << std::endl;
}

我调用 p a a 没有 p ,这正是在您的代码中发生的情况, get 函数返回& A :: a ,并使用 a 读取其值!

Did I call p from inside a? a does not have p, this is exactly what happened in your code, get function return &A::a and you use a to read its value! that's all, nothing is wrong and I think it will be compiled in all compilers.

这里还有一个问题是:为什么C ++允许声明模板使用<$ c的私有成员$ c> A 。 C ++标准说:

One other question here is: Why C++ allow declaring template using private member of A. C++ standard say:


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

14.7.2p8 The usual access checking rules do not apply to names used to specify explicit instantiations. [Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects which would normally not be accessible and the template may be a member template or member function which would not normally be accessible.]

但是如果你尝试实例化或甚至 typedef 指定的模板,那么你会得到一个错误。
稍微修改你的例子:

But if you try to instantiate or even typedef specified template then you get an error. Let's modify your example slightly:

struct A {
private:
    int a;
    friend void f();
};

// Explicit instantiation - OK, no access checks
template struct Rob<A_f, &A::a>;

// Try to use the type in some way - get an error.
struct Rob<A_f, &A::a> r;            // error
typedef struct Rob<A_f, &A::a> R;    // error
void g(struct Rob<A_f, &A::a>);      // error

// However, it's Ok inside a friend function.
void f() {
    Rob<A_f, &A::a> r;               // OK
    typedef Rob<A_f, &A::a> R;       // OK
}

这篇关于使用模板技巧访问私有成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆