Skip to content

Instantly share code, notes, and snippets.

@schaumb
Last active March 16, 2023 21:06
Show Gist options
  • Save schaumb/38006411a6daf9a1374a391d6941761c to your computer and use it in GitHub Desktop.
Save schaumb/38006411a6daf9a1374a391d6941761c to your computer and use it in GitHub Desktop.
access private c++17
#ifndef ACCESS_PRIVATE_CPP17
#define ACCESS_PRIVATE_CPP17
#include <functional>
#define ACCESS_PRIVATE_IMPL(CLASS, NAME, CASTER, TYPE) \
namespace { \
namespace access_tag::CLASS {\
template<class T>\
struct NAME; \
}\
namespace private_access_detail { \
template<class T> \
using identity = T;\
template<typename TagType, typename ...>\
struct private_access_get;\
\
template<typename ...Ts> \
struct private_access_get<access_tag::CLASS::NAME<TYPE>, Ts...> {\
friend constexpr auto getter(private_access_get<access_tag::CLASS::NAME<TYPE>, Ts...>);\
static constexpr auto get() {\
return getter(private_access_get<access_tag::CLASS::NAME<TYPE>, Ts...>{});\
}\
};\
\
template <auto PtrValue, typename TagType, typename ...>\
struct private_access;\
\
template <auto PtrValue, typename ...Ts>\
struct private_access<PtrValue, access_tag::CLASS::NAME<TYPE>, Ts...> \
: private_access_get<access_tag::CLASS::NAME<TYPE>, Ts...> {\
friend constexpr auto getter(private_access_get<access_tag::CLASS::NAME<TYPE>, Ts...>) { return PtrValue; }\
};\
}\
template struct private_access_detail::private_access<CASTER(CLASS, TYPE, &CLASS::NAME), access_tag::CLASS::NAME<TYPE>>; \
namespace access::CLASS {\
template<class Obj, class ...Args>\
constexpr static auto NAME(Obj&& obj, Args&& ...args)\
-> std::invoke_result_t<\
decltype(private_access_detail::private_access_get<access_tag::CLASS::NAME<TYPE>>::get()),\
Obj, Args...\
> {\
return std::invoke(private_access_detail::private_access_get<access_tag::CLASS::NAME<TYPE>>::get(),\
std::forward<Obj>(obj), std::forward<Args>(args)...);\
} \
}\
}
#define IDENTITY(CLASS, TYPE, X) X
#define ACCESS_PRIVATE(CLASS, NAME) ACCESS_PRIVATE_IMPL(CLASS, NAME, IDENTITY, void)
#define CASTED(CLASS, TYPE, X) static_cast<private_access_detail::identity<TYPE> CLASS::*>(X)
#define ACCESS_PRIVATE_OVERLOADED(CLASS, NAME, OVERLOAD) ACCESS_PRIVATE_IMPL(CLASS, NAME, CASTED, OVERLOAD)
/*
Usage:
class Class {
int member;
void f() {}
void fun(int) {}
void fun(double) {}
};
...
ACCESS_PRIVATE(Class, member)
ACCESS_PRIVATE(Class, f)
ACCESS_PRIVATE_OVERLOADED(Class, fun, void(int))
ACCESS_PRIVATE_OVERLOADED(Class, fun, void(double))
...
void any_fun() {
Class c;
[[maybe_unused]] int& mem = access::Class::member(c);
access::Class::f(c);
access::Class::fun(c, 5);
access::Class::fun(c, 5.4);
}
*/
#endif // ACCESS_PRIVATE_CPP17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment