一般地,C++ 不希望我们在类外直接访问类的私有成员,就连 decltype() 也不行:
class A
{
int foo(int);
};
inline static constexpr const decltype(&A::foo) c_pfn_A_foo = &A::foo; // ERR
笔者在如下两个 StackOverflow 问题中(逐步)得到了满意的解答:
- Calling private method in C++
- Search for an elegant and nonintrusive way to access private methods of a class
成品如下所示:
// PrivateAccess.h
#pragma once
template <typename Tag, typename Tag::pfn_t pfn>
struct tag_bind_pfn
{
// 这句是核心之一,巧妙利用 friend 在模板外定义了函数,还是 constexpr!
friend constexpr typename Tag::pfn_t pfn_of(Tag) { return pfn; }
};
// main.cpp
#include <cstdio>
#include "PrivateAccess.h"
class A
{
int foo(int a) { return a; }
};
struct tag_A_foo
{
using pfn_t = int (A::*)(int);
// 这句也很关键,不信你去掉试试,会编译报错
friend constexpr typename pfn_t pfn_of(tag_A_foo);
};
// 这句是核心之一,编译器允许在模板显式实例化时访问私有成员,使这一切成为可能
template struct tag_bind_pfn<tag_A_foo, &A::foo>;
// 这句纯粹向大家展示一下它可以 constexpr
inline static constexpr const auto c_pfn_A_foo = pfn_of(tag_A_foo{});
int main()
{
A p;
auto ret = (p.*(c_pfn_A_foo))(1);
printf("%d\n", ret);
return 0;
}