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