QuISP
Loading...
Searching...
No Matches
AccessPrivate.h
Go to the documentation of this file.
1
27// copy of https://github.com/martong/access_private/tree/c65d54b17bf7b212cb4df867edf143f2ebb0186a
28// clang-format off
29
30#include <utility>
31#include <type_traits>
32
33#if __cplusplus == 201103L
34namespace std {
35 template <bool B, class T = void>
36 using enable_if_t = typename enable_if<B, T>::type;
37 template <class T>
38 using remove_reference_t = typename remove_reference<T>::type;
39} // std
40#endif
41
42// Unnamed namespace is used to avoid duplicate symbols if the macros are used
43// in several translation units. See test1.
44namespace {
46
47 // @tparam TagType, used to declare different "get" funciton overloads for
48 // different members/statics
49 template <typename PtrType, PtrType PtrValue, typename TagType>
50 struct private_access {
51 // Normal lookup cannot find in-class defined (inline) friend functions.
52 friend PtrType get(TagType) { return PtrValue; }
53 };
54
55 } // namespace private_access_detail
56} // namespace
57
58// Used macro naming conventions:
59// The "namespace" of this macro library is PRIVATE_ACCESS, i.e. all
60// macro here has this prefix.
61// All implementation macro, which are not meant to be used directly have the
62// PRIVATE_ACCESS_DETAIL prefix.
63// Some macros have the ABCD_IMPL form, which means they contain the
64// implementation details for the specific ABCD macro.
65
66#define PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y) x##y
67#define PRIVATE_ACCESS_DETAIL_CONCATENATE(x, y) \
68 PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y)
69
70// @param PtrTypeKind E.g if we have "class A", then it can be "A::*" in case of
71// members, or it can be "*" in case of statics.
72#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, \
73 PtrTypeKind) \
74 namespace { \
75 namespace private_access_detail { \
76 /* Tag type, used to declare different get funcitons for different \
77 * members \
78 */ \
79 struct Tag {}; \
80 /* Explicit instantiation */ \
81 template struct private_access<decltype(&Class::Name), &Class::Name, \
82 Tag>; \
83 /* We can build the PtrType only with two aliases */ \
84 /* E.g. using PtrType = int(int) *; would be illformed */ \
85 using PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) = Type; \
86 using PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) = \
87 PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) PtrTypeKind; \
88 /* Declare the friend function, now it is visible in namespace scope. \
89 * Note, \
90 * we could declare it inside the Tag type too, in that case ADL would \
91 * find \
92 * the declaration. By choosing to declare it here, the Tag type remains \
93 * a \
94 * simple tag type, it has no other responsibilities. */ \
95 PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) get(Tag); \
96 } \
97 }
98
99#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(Tag, Class, Type, Name) \
100 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \
101 namespace { \
102 namespace access_private { \
103 Type &Name(Class &&t) { return t.*get(private_access_detail::Tag{}); } \
104 Type &Name(Class &t) { return t.*get(private_access_detail::Tag{}); } \
105 /* The following usings are here to avoid duplicate const qualifier \
106 * warnings \
107 */ \
108 using PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag) = Type; \
109 using PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) = \
110 const PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag); \
111 PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) & Name(const Class &t) { \
112 return t.*get(private_access_detail::Tag{}); \
113 } \
114 } \
115 }
116
117#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(Tag, Class, Type, Name) \
118 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \
119 namespace { \
120 namespace call_private { \
121 /* We do perfect forwarding, but we want to restrict the overload set \
122 * only for objects which have the type Class. */ \
123 template <typename Obj, \
124 std::enable_if_t<std::is_same<std::remove_reference_t<Obj>, \
125 Class>::value> * = nullptr, \
126 typename... Args> \
127 auto Name(Obj &&o, Args &&... args) -> decltype( \
128 (std::forward<Obj>(o).* \
129 get(private_access_detail::Tag{}))(std::forward<Args>(args)...)) { \
130 return (std::forward<Obj>(o).*get(private_access_detail::Tag{}))( \
131 std::forward<Args>(args)...); \
132 } \
133 } \
134 }
135
136#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD(Tag, Class, Type, \
137 Name) \
138 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \
139 namespace { \
140 namespace access_private_static { \
141 namespace Class { \
142 Type &Name() { return *get(private_access_detail::Tag{}); } \
143 } \
144 } \
145 }
146
147#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN(Tag, Class, Type, \
148 Name) \
149 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \
150 namespace { \
151 namespace call_private_static { \
152 namespace Class { \
153 template <typename... Args> \
154 auto Name(Args &&... args) -> decltype( \
155 get(private_access_detail::Tag{})(std::forward<Args>(args)...)) { \
156 return get(private_access_detail::Tag{})( \
157 std::forward<Args>(args)...); \
158 } \
159 } \
160 } \
161 }
162
163#define PRIVATE_ACCESS_DETAIL_UNIQUE_TAG \
164 PRIVATE_ACCESS_DETAIL_CONCATENATE(PrivateAccessTag, __COUNTER__)
165
166#define ACCESS_PRIVATE_FIELD(Class, Type, Name) \
167 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \
168 Class, Type, Name)
169
170#define ACCESS_PRIVATE_FUN(Class, Type, Name) \
171 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \
172 Class, Type, Name)
173
174#define ACCESS_PRIVATE_STATIC_FIELD(Class, Type, Name) \
175 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD( \
176 PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name)
177
178#define ACCESS_PRIVATE_STATIC_FUN(Class, Type, Name) \
179 PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN( \
180 PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name)
181
Definition AccessPrivate.h:45
Definition QNIC.h:49