使用模板技巧访问私人成员

access private member using template trick(使用模板技巧访问私人成员)
本文介绍了使用模板技巧访问私人成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

来自博客文章 访问私人成员:更安全的肮脏 by 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;
}

如何从 a 对象调用 get 函数,因为它没有在 class A 中定义?

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

我不明白为什么 get 必须有 Tag 作为参数而不是 a.*get()=> 好的,这是由于 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

推荐答案

你不是从 a 调用 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;
}

我是否从 a 内部调用了 p ?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++ 允许使用 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
}

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

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

How do compilers treat variable length arrays(编译器如何处理变长数组)
Deduce template argument from std::function call signature(从 std::function 调用签名推导出模板参数)
check if member exists using enable_if(使用 enable_if 检查成员是否存在)
Standard Library Containers with additional optional template parameters?(具有附加可选模板参数的标准库容器?)
Uses of a C++ Arithmetic Promotion Header(C++ 算术提升标头的使用)
Parameter pack must be at the end of the parameter list... When and why?(参数包必须位于参数列表的末尾...何时以及为什么?)