Boost logo

Boost :

From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2002-12-12 17:44:25


----- Original Message -----
From: "Augustus Saunders" <infinite_8_monkey_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Thursday, December 12, 2002 6:42 PM
Subject: [boost] Re: Optional Review, consider iterators

>
> I think that a lot of this discussion is boiling down to whether or
> not optional should sport a pointer interface at all.
>
I think that the discussion is boiling down to whether or not optional
should support relational operators, and then how should these be
defined.
We haven't really discussed whether to drop or keep the pointer interface.

> As previously
> discussed, an optional cannot--doesn't want to--support several bits
> of pointer semantics.
>
True.

> To me, the only really important benefit of pointer syntax is for
> usage in generic code.
>
This is one of the reasons, but the other really important
reason is that it looks familiar.
When you see:

if ( opt )
  foo(*opt)

you know what it is about.

> While it is a convenient shorthand in regular
> code, it is no more laborious, really, to type out some function
> calls instead of operator* and operator&.
>
But those function calls will not be familiar.
The pointer interface brings a familiar idiom to deal with optional values.

> So, if we set generic code
> aside for a moment, I think that it is clear that a pointer interface
> is dangerously misleading and should definitely be stricken.
>
It is only dangerosuly misleading if it is abused.
I seems that we all agree that operator*(), operator-> and operator
safe_bool()
are pretty safe.
The controversial part are relational operators.

> However, I want to consider generic code again. Consdier iterators
> and their (non)equivalence with pointers and how useful they are.
> Concepts were invented to convey some requirements and guarantees for
> generic code. This way, an interface that is a subset of a pointer's
> interface can still be used when that is all that is needed. If we
> want to be able to use optionals interchangeably with pointers, we
> have to define some new concepts. Additionally, we need to define
> some new traits to prevent optionals from being used in some contexts
> that might otherwise compile. Then, in theory :), all the existing
> generic boost code that can accept pointer like things needs to
> re-evaluated to see whether or not the requirements can be loosened
> to this new concept we make, and if not, to add some concept-checking
> to make sure an optional isn't used.
>
I wouldn't go so far as to make sure optional<> isn't used in place of
a generic pointer because optional is intended to serve a specific
purpose, that of conveing optionality, and not all pointers are used
for that, so it shouldn't be expected that an optional is used
for something for which it is not designed.
Anyway, I agree with you on the usefulness of new concepts.

> Personally, I think that it is a good thing to define more refined
> concepts. It helps us to think about our problems more clearly.
Indeed.

> Right now, when writing generic code, we ask ourselves, do I really
> need a RandomIterator, or will a ForwardIterator do? Then, since we
> of course document such requirements :), it adds clarity to the code.
> So, here's my stab at defining some new concepts:
>
> OptionalValue: meant to convey a value that is optional. Supports
> operator bool, operator*, and operator&, where operator bool
> indicates whether a value exists, operator* returns the value, and
> operator& returns the address of the value.
>
Why operator& instead of operator-> ?
AFAICT, both * and & are never present on the same concept.
Anyway, with -> instead of &, I agree with this definition of the
OptionalValue concept.

> Note, specifically, that
> optional values *may not be directly compared*. If you want to
> determine whether two optionals are initialized with the same value,
> you must spell it out:
>
> if (o1 && o1 && *o1 == *o2)
> {
> ...
> }
>
Absolutely agree!
This is what I originally wanted, and what I want now after all the rain :-)

>
> Examples of OptionalValue: pointers, smart pointers, optional.
>
OK.

> AliasedValue : specializes OptionalValue. An AliasedValue is an
> OptionalValue with the additional operator==. The operator== of an
> AliasedValue makes this guarantee:
>
> av1 == av2 iff (av1 && av2 && &*av1 == &*av2) || (!av1 && !av2)
>
> In other words, if two AliasedValues compare equal, then they are
> aliases for the same value. Note, however, that poor taste in
> operator overloading could satisfy the above expression without
> complying.
>
> Examples of AliasedValue: pointers, smart pointers
>
OK.

> I haven't read through the standard concept definitions in a while,
> so I may have strayed from the usual style for defining them,
> although I think my idea is clear. Now, I can write generic code:
>
> template <typename OptionalValue, typename Value>
> bool is_equal_to_value( OptionalValue ov, Value v)
> {
> if (ov)
> return *ov == v;
> else
> return false;
> }
>
OK.

> Once the language lawyers amoung us tighten down the scres on the
> OptionalValue definition, then this code makes it perfectly clear
> that pointers and optionals are completely interchangeable when
> calling is_equal_to_value. It is also equally clear that you cannot
> pass an optional to this function:
>
> template <typename AliasedValue>
> bool are_they_really_the_same_object(AliasedValue av1, AliasedValue
> av2)
> {
> return av1 == av2;
> }
>
OK.

> Now, if you want to leave a comparison operator in optional, that's
> fine so long as we define some traights so that the above code can
> concept check to make sure operator== is doing what it's supposed to.
>
I think your concepts are correctly defined.
In fact, I thought that operator== for optional could be made to
fit the AliasedValue concept, but Peter showed that it doesn't,
so I conclude that operator== should be droped.

>
> Then, code that was written specifically for optional (and
> understands the different semantics) can still take advantage of the
> convenience. However, if it was just me, I'd get rid of operator==
> altogether if this pointer path is followed.
>
This is what I will do.

Fernando Cacciola


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