There's a neat trick I've used for a while when writing C++ code: proxied data members. The idea is straight-forward. The user of your class can write normal-looking access to data member, but behind the scenes your class calls accessor member functions on the user's behalf. I was unable to find a similar technique in Boost but it is nothing new. Proxied data members relies on a helper class which curries an object pointer and member function pointers, applying them as needed via assignment and conversion operators.
The simplest form for a read-only data member is:
#include <iostream> using namespace std; template<class P, class T> class read_only { typedef T (P::*read_t) ( ) const; P &parent; read_t read; // protected: public: // no friend template parameters read_only (P &parent, read_t read) : parent (parent), read (read) { } public: operator T ( ) const { return (parent.*read) ( ); } }; class bob_t { int i; int read_i ( ) const { return i; } public: read_only<bob_t, int> roi; bob_t ( ) : i (42), roi (*this, &bob_t::read_i) { } }; int main ( ) { bob_t bob; // bob.roi = 24; // doesn't compile int i = bob.roi; cout << i << endl; }
There are a lot of details which this example glosses over including returning a const reference instead of a copy, handling other types of functions besides member functions (use Boost.Function
) and access to the constructor of read_only<P, T>
. Ideally, the constructor would be private and I could declare friend P;
, but that isn't legal C++.
The idiom for a write-only data member is similar.
No comments:
Post a Comment