Boost logo

Boost :

From: Edward Diener (eddielee_at_[hidden])
Date: 2004-05-23 15:09:00


Gennadiy Rozental wrote:
>> Some thoughts:
>>
>> 1) I would rather see a single templated type, call it property<T>
>> which took other template policy parameters denoting "readonly" etc.
>
> What is an advantage? Do you envision other types of properties?

Property is a single concept with different variations. It is clearer to me
to make those different variations template parameters rather than introduce
them as different class templates.

>
>> 2) Why "obj.member.value = t" rather than "obj.member = t" ? Surely
>> operator == can be overloaded for a write property.
>
> That's very important part of design to make sure that all write
> access to the property value goes through .value. This way I could
> textually see where my property get changed. In most cases I just
> search for property.value in sources.

It is extra code to remember for your users. The expression x.y = somevalue
is much easier to use/remember than x.y.value = somevalue. Why make your
users pay for something which for you makes it only easier to find something
in your code ?

>
>> 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.
>
> Because you couldn't override operator. ;-)

The expression "n.p_name" should create a copy of the property, and applying
the size() member function gives one the size of the copy. So
n,p_name.size() is the correct syntax and not n.p_name -> size(). In my
vision of properties, properties are not variables, but values ( ala Borland
or MS ). If one wanted to change the size of the property n.p_name, one must
write:

std::string x(n.p_name);
x.size(10);
n.p_name = x;

and not

n.p_name.size(10); // This merely changes the size of a copy

>
>>> 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.
>
> Unfortunately it's quite frequent to have a need for write access.
> First example is operator= for the owner class. To be able to
> implement it you
> need owner class to have write access to the property. And it does
> not make property "less readonly". That's why I frequently use
> BOOST_READONLY_PROPERTY( int, (foo) ) p_value;
> Another idiom that frequently require exclusive write access for
> some classes is Builder/Factory patterns. Let's say you read class
> MyClassBuilder that responsible for constructing objects of that
> class. In most cases you will be forces to make MyClassBuilder a
> friend for all properties to allow
> it to set the value. And again in most cases property is still
> readonly in it's nature.
> I am open for alternative design proposition, but usability is
> major player here. After all it simple facility for simple needs.

I understand the need, but I was really arguing semantics. I think
"readonly" properties are truly readonly by everyone once they are created.
Another name for properties which can be changed only by certain select
objects/functions, rather than "readonly", should be used.

>
>>> 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.
>
> It's actually is more complex idiom than one I am trying to model.
> But If
> you have a concrete proposition we may consider it.

Essentially the idea is that getters and setters could be passed as template
parameters in the form of boost::function<etc.> type by the property
creator. This would allow any function type of object to server as the
property getter or setter by the class property creator. Boost::function is
an overall solution to function callback. Why not use it with properties if
it can be done ?

>
>> 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.
>
> One of the reason I use property templates is to eliminate need for
> separate definition of value and accessor.

I was merely pointing out that getters and setters need not be used but an
actual variable only need be specified for holding the value of a property.
How this would be specified as a possibility along with a traditional
getter/setter, such as a boost::function<>, I don't really know right now.
Maybe as a union of choices somehow in a template parameter.

If the actual implementation were too complicated, this could be dropped,
although I can see a creator of a property<T,...> complaining that he/she
doesn't need boost::function<> ( or a member finction ) to specify a
getter/setter when a variable is good enough to hold the value of the
property instead. This complaint may obviously be more true of a getter,
which need not do any transformation before copying the value back to the
user, than a setter, which often needs to do checking before setting a
value.

>
>> 3) Since the range library has been reviewed, a property could have a
>> template parameter which could be a range for the property.
>
> Range of what?

Range of the property value. Just like a SetAProperty(somevalue) function
with non-properties, there may be a range of values for the property type
which is acceptable and, outside of which an exception may be thrown etc.

>
>> 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.
>
> Again validators/interpretators may be useful, but it's more complex
> idiom and may require much more complex design.

I agree. But it may be possible to shortcut the manual writing of validators
by passing a templated validator function or class, as a template parameter
to a policy-based property template class. Obviously the boost::range type
could be such a class on the simple level of checking that the property
value falls within a specific range when set.

>
>> 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.
>
> You want be able to get a value of readonly property.

Of course, but that doesn't mean that properties have to be member variables
themselves. The value of a property is returned as a copy of a value, but
the actual value can be a something read from a file or a database on the
fly. To me this is a central point of a property. Like getter functions, ie.
x.getSomeProperty(), an actual value for SomeProperty() does not have to be
a member variable in any form but can be manufactured as needed. That is why
one can not take the address of a property.

>
>> 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.
>
> RAD environment? I am not sure I follow what you are saying here.
> Could you elaborate.

If a property were a single type, it would be easier for a pure C++
reflection method to simply find out all public properties of a class and
present them as values which could be set by the end-user programmer at
design time. Then when a certain object, represented by the design-time RAD
creator, is actually created at run-time, all of the properties are
automatically set to the values which had been specified by the
end-user-programmer at design time. This is the way C++ Builder's Object
Inspector and Microsoft's .NET equivalent, called the Component Designer,
actually work. Of course both those implementations are using their own C++
extensions to "property" and "reflection", whereas if a property<T> template
mechansim were created and reflection became part of the language in 2008,
it could be done purely in C++ with no language extensions.

Of course it is just as viable to look for a family of "property" types in a
reflection mechanism as a single type, but I prefer the latter as a
simplification mechanism.

>
>> 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.
>
> I proposed quite simple practical tool. It may coexist with more
> complex/powerful solution. But I would like to see more concrete
> propositions.

I think the most important thing regarding my concept of a "property" is
that it is a value, not a member variable. As such the value can be read
and/or written but attempting to take the address of a property, or access
its theoretically underlying member variable, would be forbidden.

I wasn't meaning to complicate matters for you but just to offer ideas which
may make it into a better template based property mechanism. I think you
should do what you feel is right for your view of property, while possibly
listening to my view or other views, and it is up to me to present a
different version if it can be done. I fully realize that talking about
ideas, and actually implementing them are two different things, and the
latter is quite a bit more work and much harder.


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