Boost logo

Boost :

From: Edward Diener (eddielee_at_[hidden])
Date: 2004-05-23 07:55:56


Gennadiy Rozental wrote:
> Hi,
>
> I am using simple class properties facility for some time and found
> it quite useful. Actually it's nothing fancy - simple helper classes
> to eliminate repetitive setter/accessor methods (and no need for
> language extensions).
>
> Essentially if you need simple readwrite property with trivial access
> methods in you class you would instead of writing:
>
> T member;
>
> void set_member( T const& ) {...}
> T const& get_member() {...}
>
> would write:
>
> readwrite_property<T> member;
>
> Now any time you need to get a member value you would write
>
> T t = obj.member;
>
> while if you need to update the value:
>
> obj.member.value = t;
>
> It's not more nor less safe as usual get/set scheme.
>
> If you need readonly object property that get initialized in
> constructor and never updated you could use
> readonly_property template for example like this:
>
> class node {
> public:
> readonly<std::string> p_name;
> ....
>
> };
>
> Now everywhere (almost) you could just use n.p_name. To get an access
> to
> name member functions you could use operator-> like this:
>
> n.p_name->size();
>
> And nobody would be able to update readonly property value.

Some thoughts:

1) I would rather see a single templated type, call it property<T> which
took other template policy parameters denoting "readonly" etc.
2) Why "obj.member.value = t" rather than "obj.member = t" ? Surely operator
== can be overloaded for a write property.
3) Why "n.p_name -> size()" rather than n.p_name.size()" ? The variable
p_name is not a property of type pointer to std::string but rather a
property of type std::string.

>
> Finally if you need to provide a write access for readonly property
> you
> could use another form of readonly_property template. Unfortunately
> during language limitations (inability to declare template parameter
> as friend) you would need to use macro, for example like this:
>
> class foo {
> public:
> BOOST_READONLY_PROPERTY( int, (foo)(Friend2) ) p_value;
> ...
> };
>
> Now only class foo and Friend2 have a write access to the value of the
> property p_value;

I personally would eliminate this last if the property were truly readonly.
It's equivalent in my mind to declaring a const variable but letting only
special objects change it. While such an idiom may have its use, I don't
think it is the generally correct way to program. The idea of "const" means
unchangeable after it has been set and the idea of a readonly property is
the same.

Of course I am being too inflexible, but if you wanted a property which
could be changed only by select objects, I would have a property policy
which would name it something different than readonly, maybe
"onlychangeableby" or something more succinct but more understandable than
"readonly" for this type of property policy.

>
> If boosters find this functionality worth reusing I am ready to
> prepare document page describing it's usage.
> If we don't find this header eligible for review I would like to ask
> then
> for permission to at least put these templates in boost namespace
> (currently boost::unit_test), for it inconvenience for me to keep it
> in deep namespace for rest of my current development.

I have thought about properties, in the Borland and MS .NET terms, for
awhile as being doable in pure C++. I am glad someone else has tackled it
even on as simple a basis as you have done for your own use. I believe a
slightly fuller treatment might be eventually beneficial. Here are some
further ideas:

1) One could use boost::function to specify the read and write functors
which get called whenever read or write access to a property's value was
needed.
2) As in the Borland property implementation, a property doesn't necessarily
need a read/write function but may "point to" a member variable, usually
private, which holds the actual property value.
3) Since the range library has been reviewed, a property could have a
template parameter which could be a range for the property.
4) A range may not be enough to specify all valid values for a property, so
that when a user of the property attempts to set a value which is not valid,
the code could throw an exception, assert, or silently ignore the attempted
change, all of which actions should be choosable by the end user as a
property policy.
4) Properties themselves do not necessarily have to be actual objects.
Because of that, all attempts to get an address from a property should be
short-circuited. Only its value matters.
5) If properties are a single type, with various policies, once the
capabilities of reflection are added to C++ via the work Mr. Stroustrup is
doing, it is possible for C++ properties to be used in RAD environments in
much the same way that Borland has done with C++ Builder ( now a dead
product unfortunately ) and MS is doing with Managed C++/.NET ( still a very
alive product thank to Herb Sutter's and others efforts ). This is one of
the main reasons I would like to see the pure C++ idea of property as a
single templated type with different template policies determining its
usage.

Anyway, please don't let all these ideas stop you from offering what you
have done for yourself to Boost. They are only thoughts about a more general
property facility.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk