Boost logo

Boost :

Subject: Re: [boost] [review][constrained_value] Review of Constrained Value Library begins today
From: Thorsten Ottosen (thorsten.ottosen_at_[hidden])
Date: 2008-12-08 07:56:06

Robert Kawulak skrev:
> Hi Thorsten,
> 2008/12/5 Thorsten Ottosen <thorsten.ottosen_at_[hidden]>:
>> It has been advocated in other context as well, e.g. by scott meyers. The
>> author of the bimap library was, initially, against it, citing some of the
>> same sources as you do. He ended up being very happy with the members IIRC.
>> The discussion in [*] and other places is not great IMO.
> Apparently there are groups of people that prefer either of the
> approaches, but I wouldn't like the review to become an ideological
> discussion on general style guidelines like this one.

Well, sometimes that is needed too.

>> template <typename V, typename C, typename E, typename T>
>> void change_constraint(constrained<V, C, E> & c, const T & new_constraint)
>> {
>> constrained<V, C, E> tmp(c.value(), new_constraint, c.error_handler());
>> c.swap(tmp);
>> }
>> this seems *very inefficient* compared to only changing the constraint.
> You can't simply change the constraint if the current value does not
> conform to it.You have to check that and eventually copy the value and
> the constraint, call the error policy for them and assign them back.
> In most common cases this seems not much more efficient than copying
> the whole object and swapping it (considering the typical case when
> one or both of the policies are empty or have trivial copy).
> Having said that, I agree with you at this point -- implementing
> change_constraint as a member might allow for more efficient
> implementation for some cases. This is an argument that might convince
> me to make it a member and I will investigate this possibility.

It seems to me that it must be possible to check the new constraint
without creating a new object.

Often T is int or some other small build-in type, but I guess someone
might use the library with a more heavy type.

> But in
> general I still prefer writing non-members if there's no apparent
> reason why not to do so.
>> (b) The second claim is that free-standing functions break apart monolothic
>> classes. That may be, but you don't have a monolothic class (you're not even
>> close).
> So how many functions that are unnecessarily members of a class must
> the class have to call it monolithic and to un-member those functions?
> :P

The classical example is std::string which is also what Sutter and
Alexandrescu give as an example. But here the problem is that
std::string are reimplementing generic algorithms.

You don't have a monolithic class. Just like std::vector is not
monolithic because erase is a member and not a free-standing function.
This is another issue: functions that change the invariant-defining
state of objects should be members.

>> And then finally my point, that the boost namespace is poluted with names
>> that makes it near impossible to find the right function, and so, by making
>> it a member that task is trivial.
> Note that this function is in constrained_value namespace and does not
> pollute boost namespace.


> It is not that hard to find it, your editor
> may also help when you type '::' (although I agree that typing an
> object's name and '.' may be slightly more convenient).
>> In conclusion: making something a non-member is rarely a good idea.
> In contrast: making everything a member is rarely a good idea. ;-)

Not when your modifying state, nor when you want to make the interface
most easy to use.

I'll give a good example of when a member should not have been added.
Again, let's look at the (new) C++ standard library: they have added
cbegin() and cend() members to all containers such that one can get
a const_iterator from a mutable object. Instead, two generic function
templates could have provided the same functionality with an O(1) coding
effort vs. the chosen O(n) coding effort.


Boost list run by bdawes at, gregod at, cpdaniel at, john at