This answer is based on the exact concept demonstrated by @Johannes answer / blog , as it seems to be the only "legal" way. I have turned this sample code into a handy utility. It is easily compatible with C ++ 03 (by implementing std::remove_reference and replacing nullptr ).
Library
#define CONCATE_(X, Y) X##Y #define CONCATE(X, Y) CONCATE_(X, Y) #define ALLOW_ACCESS(CLASS, TYPE, MEMBER) \ template<typename Only, TYPE CLASS::*Member> \ struct CONCATE(MEMBER, __LINE__) { friend TYPE (CLASS::*Access(Only*)) { return Member; } }; \ template<typename> struct Only_##MEMBER; \ template<> struct Only_##MEMBER<CLASS> { friend TYPE (CLASS::*Access(Only_##MEMBER<CLASS>*)); }; \ template struct CONCATE(MEMBER, __LINE__)<Only_##MEMBER<CLASS>, &CLASS::MEMBER> #define ACCESS(OBJECT, MEMBER) \ (OBJECT).*Access((Only_##MEMBER<std::remove_reference<decltype(OBJECT)>::type>*)nullptr)
API
ALLOW_ACCESS(<class>, <type>, <member>);
Using
ACCESS(<object>, <member>) = <value>; // 1 auto& ref = ACCESS(<object>, <member>); // 2
struct X { int get_member () const { return member; }; private: int member = 0; }; ALLOW_ACCESS(X, int, member); int main() { X x; ACCESS(x, member) = 42; std::cout << "proof: " << x.get_member() << std::endl; }
iammilind Jan 01 '16 at 15:25 2017-01-01 15:25
source share