Re: [boost] Formal review: Optional library

2002-12-19 Thread Douglas Gregor
On Monday 09 December 2002 11:55 am, Douglas Gregor wrote:
> The formal review of Fernando Cacciola's Optional library begins today and
> runs until the end of Wednesday, December 18.

The review of Fernando Cacciola's Optional library has ended. I will post 
review results this weekend. A hearty "thank you" goes to all reviewers.

Doug Gregor
[EMAIL PROTECTED] (Optional review manager)
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-13 Thread Anthony Williams
Fernando Cacciola writes:
 > 
 > - Original Message -
 > From: "Anthony Williams" <[EMAIL PROTECTED]>
 > To: "Boost mailing list" <[EMAIL PROTECTED]>
 > Sent: Tuesday, December 10, 2002 9:46 AM
 > Subject: Re: [boost] Formal review: Optional library
 > 
 > 
 > > Fernando Cacciola writes:
 > > Given empty(), I see no need for peek() _and_ get_value() --- if you can
 > get a
 > > reference to the value, you can get its address, if necessary.
 > >
 > Only if the optional<> is initialized.
 > peek() returns NULL in case the optional<> is uninitialized,
 > saving the user from having to test for it separately.
 > 
 > In fact, the whole point of pointer semantic is to allow the user to
 > deal with the uninitialized case conveniently, without having to
 > test empty() (or whatever) explicitely all the time.

It doesn't really help, though --- to do anything useful with the pointer, you
have to check for NULL anyway, so it's not that different.
 
 > >
 > > I prefer the member interface to the non-member interface, in this
 > instance.
 > >
 > I don't. Member functions are tightly coupled with class types.
 > As I said earlier, the usages of optional<> easely allows the code to
 > replace
 > optional<> with bare pointers.
 > This wouldn't be possible if member functions were used.

Bare pointers have quite different properties --- for one, they don't contain
the pointed-to object.

However, if you want to go down that route, then I think you ought to have an
interface as close to that of a smart pointer (such as boost::shared_ptr or
boost::scoped_ptr) as possible --- though the fact that optional<> will
contain the pointed-to object will have to affect the interface in some
way. This should be the only difference though.

Anthony
-- 
Anthony Williams
Senior Software Engineer, Beran Instruments Ltd.
Remove NOSPAM when replying, for timely response.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Joel de Guzman
- Original Message - 
From: "David Abrahams" <[EMAIL PROTECTED]>

> > Optional does not have pointer semantics. Two optionals can never alias each
> > other. "Consistent with pointer semantics" doesn't make sense. Optional is
> > not a pointer. Don't try to make it into one; you'll arrive at shared_ptr.
> > ;-)
> 
> As usual, I agree with Peter

I completely agree with Peter as well. Optional is not a pointer.
I will reiterate my position on this: optional is equivalent to
variant in behavior. Is it a container as Peter suggested?
Yes, in the same way that variant is a container that 
holds one of T0..TN (one at a time) and in the same way that 
tuple is also a container that holds T0..TN simultaneously.

Implementation issues notwithstanding (and we've shown that
optional can be implemented in terms of variant), The behavior
of the optional should be that of the variant.

While on the surface, optional looks like a pointer, and in fact
it is meant to replace some uses of pointers, A replaced by B
does not automatically mean that B is an A! 

Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread William E. Kempf
Fernando Cacciola said:
> Due to some significant changes to the optional<> class, I had to upload
> a new version so that the review can continue based on the revised
> class.
>
> http://groups.yahoo.com/group/boost/files/optional.zip
>
> The new zip contains the new code, new test and new documentation.
>
> NOTE: The header optional_detail is no longer needed so you may remove
> it before unpacking the zip.

Documentation issues/questions:

* "its safe on most platforms which treat null pointer dereferencing as
undefined behaviour which is effectively a core dump or an non-language
exception"

I know what you're saying here, but I don't like it.  Undefined behavior
is undefined behavior, and can never be considered "safe".  I'm not sure
how to rework it to convey what you want, but I think it needs reworked.

* The "safe bool" should be documented in the same manner as it is in
shared_ptr, i.e. "operator unspecified-bool-type() const; // never
throws".

* Does the "assert(*opt == v)" in the description for "explicit
optional::optional( T const& v )" indicate that the type T must be
comparable?  (I know the documentation clearly says otherwise, but it's
not clear that this is a non-normative part of the documentation.)

* In the acknowledgements for Gennadiy Rozental you describe the "value
based" implementation which no longer exists.

Interface issues/questions:

* Is there a reason for operator!() when we have the safe bool?

* Should you provide a templated assignment to parallel the templated
constructor?

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > optional m(t);
> >
> > > foo(m, m); // comparison inside yields false

where foo is

void foo(optional const &, optional const &);

> > >
> Nop... :-)
> 
> it compares true because get_pointer(x)==get_poiner(x) is true for any x,
> whether initialized or not.

True. Had foo been

void foo(optional, optional);

or had the call been

foo(optional(t), optional(t)); // corresponds to foo(&t, &t)

I would have been right.
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 5:35 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Peter Dimov" <[EMAIL PROTECTED]>
>
> Oops,
>
> > Yes it will. :-)
> >
> > optional m;
>
> should have been
>
> optional m(t);
>
> > foo(m, m); // comparison inside yields false
> >
Nop... :-)

it compares true because get_pointer(x)==get_poiner(x) is true for any x,
whether initialized or not.

In fact, this is the very reason why I choosen this definition. It matches
pointer aliasing.

Fernando Cacciola





___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola

- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 5:31 PM
Subject: Re: [boost] Formal review: Optional library


>
> Fernando Cacciola said:
> > From: "Peter Dimov" <[EMAIL PROTECTED]>
> >> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> >> > From: "Peter Dimov" <[EMAIL PROTECTED]>
> >> > optional<> is not intended to replace _all_ situations were optional
> >> values
> >> > are used.
> >> > It is itended to be used on those situations were pointers are
> >> difficult
> >> to
> >> > use;
> >> > but I expect programmers to keep using pointers were appropriate.
> >> For example, as I said before, optional arguments to a function
> >> should
> > not
> >> > be coded
> >> > with optional<> but with conventional pointers.
> >>
> >> Actually (just a minor observation)
> >>
> >> void f(optional /*const &*/ opt);
> >>
> >> is different than
> >>
> >> void f(T const * pt);
> >>
> >> as the latter might potentially store 'pt' while the former cannot.
> >>
> > ? You mean that the code inside f() could hold onto 'pt'?
> > Well, yes it can... but that would be nasty.
> > It is supposed to know that ownership is not being handed in.
> > The use of a pointer is reserved to convey optionality.
>
> It is?  Then how do you ever transfer ownership ;).
>
Hmm... OK, I take that back.
A function can use a pointer to optionally take ownership of an object.
So optional as an argument could communicate that this is not the case,
which is what Peter meant (I think...)

Fernando Cacciola


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola
Due to some significant changes to the optional<> class, I had to upload a
new version so that the review can continue based on the revised class.

http://groups.yahoo.com/group/boost/files/optional.zip

The new zip contains the new code, new test and new documentation.

NOTE: The header optional_detail is no longer needed so you may remove it
before unpacking the zip.

Thanks.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Peter Dimov" <[EMAIL PROTECTED]>

Oops,

> Yes it will. :-)
> 
> optional m;

should have been

optional m(t);

> foo(m, m); // comparison inside yields false
> 
> T * p;

and this should have been

T * p = &t;

> foo(p, p); // comparison inside yields true

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread William E. Kempf

Fernando Cacciola said:
> From: "Peter Dimov" <[EMAIL PROTECTED]>
>> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>> > From: "Peter Dimov" <[EMAIL PROTECTED]>
>> > optional<> is not intended to replace _all_ situations were optional
>> values
>> > are used.
>> > It is itended to be used on those situations were pointers are
>> difficult
>> to
>> > use;
>> > but I expect programmers to keep using pointers were appropriate.
>> For example, as I said before, optional arguments to a function
>> should
> not
>> > be coded
>> > with optional<> but with conventional pointers.
>>
>> Actually (just a minor observation)
>>
>> void f(optional /*const &*/ opt);
>>
>> is different than
>>
>> void f(T const * pt);
>>
>> as the latter might potentially store 'pt' while the former cannot.
>>
> ? You mean that the code inside f() could hold onto 'pt'?
> Well, yes it can... but that would be nasty.
> It is supposed to know that ownership is not being handed in.
> The use of a pointer is reserved to convey optionality.

It is?  Then how do you ever transfer ownership ;).

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> From: "Peter Dimov" <[EMAIL PROTECTED]>
[...]
> > if(both uninitialized)
> > {
> > // do nothing, nothrow
> > }
> > else if(one initialized, one not)
> > {
> > lhs.reset(*rhs); // strong
> > rhs.reset(); // nothrow
> > }
> > else // both initialized
> > {
> > using std::swap;
> > swap(*lhs, *rhs);
> > }
> >
> > It doesn't even need friendship.
> >
> I see.
> Q: This code is supposed to be in boost::swap( optional&,
optional&)?

Yep.

> > void f(optional /*const &*/ opt);
> >
> > is different than
> >
> > void f(T const * pt);
> >
> > as the latter might potentially store 'pt' while the former cannot.
> >
> ? You mean that the code inside f() could hold onto 'pt'?
> Well, yes it can... but that would be nasty.
> It is supposed to know that ownership is not being handed in.
> The use of a pointer is reserved to convey optionality.

No, functions that store an address use by-pointer, too, even when it must
not be NULL. Consider:

void f(int const & r); // stores &r

f(5L);

> If I have:
>
> void foo ( optional x, optional y )
> {
>   ( x == y ) ;
> }
>
> Why do you suggest to be the semantic of the comnparison?
>
> I think that you suggest that it is:
>
> ( (!x) != (!y) ? false : ( !x ? true : ( *x == *y ) )
>
> but in this case, replacing optional with T* changes this semantic,
which
> is what I object.
>
> OTOH, my definition as:  get_pointer(x) == get_pointer(y)
>
> will not change the semantic of the comparison if optional is replaced
by
> T*

Yes it will. :-)

optional m;

foo(m, m); // comparison inside yields false

T * p;

foo(p, p); // comparison inside yields true

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola
- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 3:59 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > From: "Peter Dimov" <[EMAIL PROTECTED]>
> > > True, swap()'s guarantees depend on the type. If T provides a
> > > nothrow/strong/basic swap, optional::swap should be at least
> > > nothrow/strong/basic, respectively. I think that this can be done
> provided
> > > that T(T const &) is strong and T::~T is nothrow.
> > >
> > I still have to tink about this ...
>
> This is how it works in my mind:
>
> if(both uninitialized)
> {
> // do nothing, nothrow
> }
> else if(one initialized, one not)
> {
> lhs.reset(*rhs); // strong
> rhs.reset(); // nothrow
> }
> else // both initialized
> {
> using std::swap;
> swap(*lhs, *rhs);
> }
>
> It doesn't even need friendship.
>
I see.
Q: This code is supposed to be in boost::swap( optional&, optional&)?

> [...]
>
> > optional<> is not intended to replace _all_ situations were optional
> values
> > are used.
> > It is itended to be used on those situations were pointers are difficult
> to
> > use;
> > but I expect programmers to keep using pointers were appropriate.
> > For example, as I said before, optional arguments to a function should
not
> > be coded
> > with optional<> but with conventional pointers.
>
> Actually (just a minor observation)
>
> void f(optional /*const &*/ opt);
>
> is different than
>
> void f(T const * pt);
>
> as the latter might potentially store 'pt' while the former cannot.
>
? You mean that the code inside f() could hold onto 'pt'?
Well, yes it can... but that would be nasty.
It is supposed to know that ownership is not being handed in.
The use of a pointer is reserved to convey optionality.


> > Therefore, the shortcut which is gained by having (o1==o2) compare
values,
> > handling
> > uninitialized cases, is in itself very useful, but gives optional<> a
> > peculiarity
> > which spoils its ubiquity.
>
> Not necessarily. Please read my explanation of equivalence in the other
> post, and note that it applies to pointers, too.
>
I don't get it...

If I have:

void foo ( optional x, optional y )
{
  ( x == y ) ;
}

Why do you suggest to be the semantic of the comnparison?

I think that you suggest that it is:

( (!x) != (!y) ? false : ( !x ? true : ( *x == *y ) )

but in this case, replacing optional with T* changes this semantic, which
is what I object.

OTOH, my definition as:  get_pointer(x) == get_pointer(y)

will not change the semantic of the comparison if optional is replaced by
T*

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola
- Original Message -
From: "David Abrahams" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 3:45 PM
Subject: Re: [boost] Formal review: Optional library


> >
> > In order to achieve this, I considered fundamental the following
> > rule of thumb:
> > If optional<> is replaced by a pointer, and provided that uninitialized
> > optionals are defined as null pointers, any exression using optionals
> > should either fail to compile or behave exactly the same.
> > This rule allows the programmer to unambiguously infer the
> > semantic of a given expression using optional.
>
> Have you got even a single real use-case where an optional can be
> usefully substituted for a pointer in generic code?
>
> I think it's important to have a few of these in hand before
> predicating interface design principles on the idea.
>
Fair enough.

I have not exactly replaced it in a completely generic code (a templated
algorithm),
but I had

(A)
replaced optional by shared_ptr many times:
this happens when the optional object grows too much for the deep-copy of
optional<>.
In this case, I switch to shared_ptr<> with dynamic allocation.
The recievers of the optional objects never had to change beyond the type of
the variables used.

(B)
replaced optional as function arguments with pointers.
At some point I realized that the code inside the function would actually
behave
exactly the same even if the argument were pointers instead of optional<>.
Then I deprecated optional<> as arguments to functions because they were
unnecesary; but the point is that I never had to worry about the semantics
inside the function.

I concede that the above 'design principle' is more a desire than an
achieved goal,
but it is a useful one, IMO.
If you change from optional<> to pointers, the lower the impact the better.
Maybe the proposed interface doesn't give you this much, but clearly,
allowing relop
to compare values without the explicit dereference would spoil any chance of
fulfilling
this principle.

As it is currently specified, changes would have to be made on the
value-semantics (container-like)
part of the interface.
relational operators will appear on boolean contexts just like safe_bool, so
you would
have expressions testing for initialization states: ( opt == 0 ), and
expressions
testing for value equality: ( opt1 == opt2 ) both with the same syntax.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Formal review: Optional library

2002-12-12 Thread Iain K.Hanson


> [mailto:[EMAIL PROTECTED]]On Behalf Of David Abrahams
> Sent: 12 December 2002 19:03
> 

>But it doesn't, really.  If you're going to have deep constness and
>deep assignment, the only thing remaining that makes it pointer-like
>is the operator*/operator-> interface.  At that point, it's just a
>very convenient shorthand for saying .front()/.begin() on a
>container-of-1. 

I understand. But, in general, I don't think users will find it
intutative to think of it as a container of one. Given that it
is only sytactic sugar I would probably prefer that they be left
undefined then, as I suspect that they will cause confusion. 

>??? it's not as though the function returns false randomly!

I never implied that it did!

>It tells you whether one optional is substitutable for another in the
>same expression (ignoring the address-of operator), which is the
>essence of equivalence in C++.

I understood that the first time it was said. I don't feel strongly
enough about this though to carry the argument on further. Just my
2p worth.

/ikh
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread David Abrahams
"Iain K.Hanson" <[EMAIL PROTECTED]> writes:

>> [mailto:[EMAIL PROTECTED]]On Behalf Of David Abrahams
>> Sent: 12 December 2002 18:16
>> 
>
>>1.  The contained value is part of the state.  Pretending otherwise
>>just confuses everything.
>
> Whether it is initialised is orthaganal to its contained value. As
> Bill Kempf said "if it walks like a duck and talks like a duck".

But it doesn't, really.  If you're going to have deep constness and
deep assignment, the only thing remaining that makes it pointer-like
is the operator*/operator-> interface.  At that point, it's just a
very convenient shorthand for saying .front()/.begin() on a
container-of-1. 

> There is no confusion, there are two different ways of looking at
> them. I can see the logic in Peter's view, I just think that like 
> pointers, equivelence of optional's is not about there contained
> value, it is about whether they have been initialised or not. The
> name of the class say's it.

I don't see how the name of the class implies anything.  If I have two
optional integers, 3 and 4, I naturally think of them as unequal.

>>2.  As long as there's a way to check for an emptiness mismatch (what
>>you're calling a "state mismatch", e.g. x.empty() == y.empty()), I
>>don't why there's a problem that operator== doesn't make that
>>distinction clear.
>
> As I said previously, its syntatic sugar. There is nothing that you
> need the rel-ops for that you can not do another way.
>
>
>>How is Peter's suggestion less-useful?
>
> because the false result tells you nothing.

??? it's not as though the function returns false randomly!

It tells you whether one optional is substitutable for another in the
same expression (ignoring the address-of operator), which is the
essence of equivalence in C++.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> From: "Peter Dimov" <[EMAIL PROTECTED]>
> > True, swap()'s guarantees depend on the type. If T provides a
> > nothrow/strong/basic swap, optional::swap should be at least
> > nothrow/strong/basic, respectively. I think that this can be done
provided
> > that T(T const &) is strong and T::~T is nothrow.
> >
> I still have to tink about this ...

This is how it works in my mind:

if(both uninitialized)
{
// do nothing, nothrow
}
else if(one initialized, one not)
{
lhs.reset(*rhs); // strong
rhs.reset(); // nothrow
}
else // both initialized
{
using std::swap;
swap(*lhs, *rhs);
}

It doesn't even need friendship.

[...]

> optional<> is not intended to replace _all_ situations were optional
values
> are used.
> It is itended to be used on those situations were pointers are difficult
to
> use;
> but I expect programmers to keep using pointers were appropriate.
> For example, as I said before, optional arguments to a function should not
> be coded
> with optional<> but with conventional pointers.

Actually (just a minor observation)

void f(optional /*const &*/ opt);

is different than

void f(T const * pt);

as the latter might potentially store 'pt' while the former cannot.

> Therefore, the shortcut which is gained by having (o1==o2) compare values,
> handling
> uninitialized cases, is in itself very useful, but gives optional<> a
> peculiarity
> which spoils its ubiquity.

Not necessarily. Please read my explanation of equivalence in the other
post, and note that it applies to pointers, too.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread David Abrahams
"Fernando Cacciola" <[EMAIL PROTECTED]> writes:

> - Original Message -
> From: "Peter Dimov" <[EMAIL PROTECTED]>
> To: "Boost mailing list" <[EMAIL PROTECTED]>
> Sent: Thursday, December 12, 2002 1:00 PM
> Subject: Re: [boost] Formal review: Optional library
>
>
>> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>> > > Yes, I thought about that, too. But if the current swap semantics are
>> > > retained, it should simply be removed. Otherwise optional::swap
> must
>> > > offer at least swap(T&, T&)'s guarantee.
>> > >
>> > I'm not sure I follow.
>> > What are swap(T&, T&) guarantees in general?
>> > I thought this depended on the specific type.
>>
>> True, swap()'s guarantees depend on the type. If T provides a
>> nothrow/strong/basic swap, optional::swap should be at least
>> nothrow/strong/basic, respectively. I think that this can be done provided
>> that T(T const &) is strong and T::~T is nothrow.
>>
> I still have to tink about this ...
>
>> > Anyway, as I posted recently, I'm just about to conclude that relational
>> > operators
>> > could be properly defined as a synonim for: get_pointer(o1) .relop.
>> > get_pointer(o2).
>> > I found this definition totally consistent with pointer semantics and
> the
>> > implied
>> > aliasings.
>>
>> Optional does not have pointer semantics.
>>
> Not _entirely_, sure; but I think it can be accurately said
> that it has _partly_ pointer semantics, which is reflected
> by its pointer-like interface, and _partly_ value semantics,
> which is reflected by its container-like interface.
>
> Precisely because its dual nature can be confusing,
> it is very important that boths parts of the interface,
> which reflect different semantics, can be unambiguously
> differentiated so the actual semantic can be inferred
> without doubts.
>
> In order to achieve this, I considered fundamental the following
> rule of thumb:
> If optional<> is replaced by a pointer, and provided that uninitialized
> optionals are defined as null pointers, any exression using optionals
> should either fail to compile or behave exactly the same.
> This rule allows the programmer to unambiguously infer the
> semantic of a given expression using optional.

Have you got even a single real use-case where an optional can be
usefully substituted for a pointer in generic code?

I think it's important to have a few of these in hand before
predicating interface design principles on the idea.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Formal review: Optional library

2002-12-12 Thread Iain K.Hanson


> [mailto:[EMAIL PROTECTED]]On Behalf Of David Abrahams
> Sent: 12 December 2002 18:16
> 

>1.  The contained value is part of the state.  Pretending otherwise
>just confuses everything.

Whether it is initialised is orthaganal to its contained value. As
Bill Kempf said "if it walks like a duck and talks like a duck".
There is no confusion, there are two different ways of looking at
them. I can see the logic in Peter's view, I just think that like 
pointers, equivelence of optional's is not about there contained
value, it is about whether they have been initialised or not. The
name of the class say's it.

>2.  As long as there's a way to check for an emptiness mismatch (what
>you're calling a "state mismatch", e.g. x.empty() == y.empty()), I
>don't why there's a problem that operator== doesn't make that
>distinction clear.

As I said previously, its syntatic sugar. There is nothing that you
need the rel-ops for that you can not do another way.

>How is Peter's suggestion less-useful?

because the false result tells you nothing.

/ikh
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 1:00 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > > Yes, I thought about that, too. But if the current swap semantics are
> > > retained, it should simply be removed. Otherwise optional::swap
must
> > > offer at least swap(T&, T&)'s guarantee.
> > >
> > I'm not sure I follow.
> > What are swap(T&, T&) guarantees in general?
> > I thought this depended on the specific type.
>
> True, swap()'s guarantees depend on the type. If T provides a
> nothrow/strong/basic swap, optional::swap should be at least
> nothrow/strong/basic, respectively. I think that this can be done provided
> that T(T const &) is strong and T::~T is nothrow.
>
I still have to tink about this ...

> > Anyway, as I posted recently, I'm just about to conclude that relational
> > operators
> > could be properly defined as a synonim for: get_pointer(o1) .relop.
> > get_pointer(o2).
> > I found this definition totally consistent with pointer semantics and
the
> > implied
> > aliasings.
>
> Optional does not have pointer semantics.
>
Not _entirely_, sure; but I think it can be accurately said
that it has _partly_ pointer semantics, which is reflected
by its pointer-like interface, and _partly_ value semantics,
which is reflected by its container-like interface.

Precisely because its dual nature can be confusing,
it is very important that boths parts of the interface,
which reflect different semantics, can be unambiguously
differentiated so the actual semantic can be inferred
without doubts.

In order to achieve this, I considered fundamental the following
rule of thumb:
If optional<> is replaced by a pointer, and provided that uninitialized
optionals are defined as null pointers, any exression using optionals
should either fail to compile or behave exactly the same.
This rule allows the programmer to unambiguously infer the
semantic of a given expression using optional.

> Two optionals can never alias each
> other.
Unless they are both uninitialized or are actually the same.

> "Consistent with pointer semantics" doesn't make sense.
Why?
The pointer-like interface associates a pointer value to an optional object.
Having relop be defined to compare this pointer value makes just as much
sense
as having operator*() dereference this pointer, having operator-> return it,
etc...

>Optional is not a pointer. Don't try to make it into one; you'll arrive at
shared_ptr.
> ;-)
>
It is not completely a pointer, neither is not completely not a pointer. :-)

In fact, shared_ptr<> can well be used to convey the same optionality of a
value.
This is important: in an optional-less world, pointers and smart-pointers
are used
to handle optional values.
This makes a lot of sense and works pretty well in many situations.
It is actually the choice of value _storage_ which decides whether to
use optional<> or shared_ptr<>. If it makes sense to allocate the optional
object
dynamically, then using shared_ptr<> is a very good choice; but if the
ubiquity of
the type makes a dynamic allocation wastefull, go with optional<>.
But from the reciever POV, it should be the same whether a builtin pointer,
a smart pointer, or optional was used.
This is why the poiner-like interface is important.

The difference between using a pointer (smart or not) or using optional
shall
not be found on the operations that access the value, this is unnecesary.
The difference shall be in the way the value is wrapped: optional<> uses
value
semantics for this part, which is what makes it usefull, since it saves you
from
a wastefull and protocolar dynamic allocation/deallocation; but that's is
its
fundamental purpose; for the rest, familliar smart-pointer semantics are
appropiate.

Thus, optional<> uses a pointer-like interface for everthing except those
operations that deal with initializing, replacing and uninitializing the
value.


I know that (*o1==*o2) is undefined for uninitialized optionals,
but this is equally undefined for pointers, so I don't see it as
such a big problem.
optional<> is not intended to replace _all_ situations were optional values
are used.
It is itended to be used on those situations were pointers are difficult to
use;
but I expect programmers to keep using pointers were appropriate.
For example, as I said before, optional arguments to a function should not
be coded
with optional<> but with conventional pointers.
Therefore, the shortcut which is gained by having (o1==o2) compare values,
handling
uninitialized cases, is in itself very useful, but gives optional<> a
peculiarity
which spoils its ubiquity.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread David Abrahams
"Iain K.Hanson" <[EMAIL PROTECTED]> writes:

>> [mailto:[EMAIL PROTECTED]]On Behalf Of Peter Dimov
>> Sent: 12 December 2002 17:09
>>
>> From: "Iain K.Hanson" <[EMAIL PROTECTED]>
>> >
>> > :-) true. But it also does not have container semantics either.
>> > I prefered your analogy with a special valued INT. Given that we
>> > have
>> > *opt1 == *opt2
>> > for ordinary value comparisons
>>
>> But this doesn't work when one of the optionals is
>> uninitialized. opt1 ==
>> opt2 (as proposed) is a safer version of the above, as its behavior is
>> always defined. It also has the desirable property
>>
>> optional b(a);
>> assert(b == a);
>>
>> for any a (i.e. it represents "equivalent to" as used by
>> CopyConstructible
>> and Assignable.)
>>
>
> given that dereference is defined then the *potentially* unsafe
> *opt1 == *opt2 is defined. However the lack of safty is very small
> as C++ programmers have to be very aware that dereferencing an
> uninitiallised pointer does very bad things at run time. This is so
> ingrained that I can't see the problem.
>
> Given the above, I can't see the utility of defining rel-ops with container
> semantics. Particularly as if opt1 == opt2 returns false you have no idea
> if it is because there is a value mis-match or a state mis-match.

1.  The contained value is part of the state.  Pretending otherwise
just confuses everything.

2.  As long as there's a way to check for an emptiness mismatch (what
you're calling a "state mismatch", e.g. x.empty() == y.empty()), I
don't why there's a problem that operator== doesn't make that
distinction clear.

> I can see the logic in your argument, but given that optional is
> neither "fish nor fowl" ( its not a smart pointer, its not a
> container, and its not just a value ), I would rather go for the
> semantics that offer most utility.

How is Peter's suggestion less-useful?

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Iain K.Hanson" <[EMAIL PROTECTED]>
>
> Given the above, I can't see the utility of defining rel-ops with
container
> semantics.

I did not say that there is utility in the "equivalence" semantics (although
they do make specifying and testing postconditions easier.) I am saying that
these are the only semantics that make sense, if comparisons are supported
at all.

> Particularly as if opt1 == opt2 returns false you have no idea
> if it is because there is a value mis-match or a state mis-match.

This is how equivalence works. It doesn't tell you anything about opt1 or
opt2, it only tells you whether the two are equivalent, i.e. whether opt2
can be substituted for opt1 in an expression with the end result being the
same. (For any type.)

> I can see the logic in your argument, but given that optional is neither
> "fish nor fowl" ( its not a smart pointer, its not a container, and its
not
> just a value ), I would rather go for the semantics that offer most
utility.

That's fine. State comparisons offer no utility. ;-)

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Formal review: Optional library

2002-12-12 Thread Iain K.Hanson


> [mailto:[EMAIL PROTECTED]]On Behalf Of Peter Dimov
> Sent: 12 December 2002 17:09
>
> From: "Iain K.Hanson" <[EMAIL PROTECTED]>
> >
> > :-) true. But it also does not have container semantics either.
> > I prefered your analogy with a special valued INT. Given that we
> > have
> > *opt1 == *opt2
> > for ordinary value comparisons
>
> But this doesn't work when one of the optionals is
> uninitialized. opt1 ==
> opt2 (as proposed) is a safer version of the above, as its behavior is
> always defined. It also has the desirable property
>
> optional b(a);
> assert(b == a);
>
> for any a (i.e. it represents "equivalent to" as used by
> CopyConstructible
> and Assignable.)
>

given that dereference is defined then the *potentially* unsafe
*opt1 == *opt2 is defined. However the lack of safty is very small as
C++ programmers have to be very aware that dereferencing an uninitiallised
pointer does very bad things at run time. This is so ingrained that I can't
see the problem.

Given the above, I can't see the utility of defining rel-ops with container
semantics. Particularly as if opt1 == opt2 returns false you have no idea
if it is because there is a value mis-match or a state mis-match.

I can see the logic in your argument, but given that optional is neither
"fish nor fowl" ( its not a smart pointer, its not a container, and its not
just a value ), I would rather go for the semantics that offer most utility.

/ikh

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Iain K.Hanson" <[EMAIL PROTECTED]>
>
> :-) true. But it also does not have container semantics either.
> I prefered your analogy with a special valued INT. Given that we
> have
> *opt1 == *opt2
> for ordinary value comparisons

But this doesn't work when one of the optionals is uninitialized. opt1 ==
opt2 (as proposed) is a safer version of the above, as its behavior is
always defined. It also has the desirable property

optional b(a);
assert(b == a);

for any a (i.e. it represents "equivalent to" as used by CopyConstructible
and Assignable.)

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Formal review: Optional library

2002-12-12 Thread Iain K.Hanson


> [mailto:[EMAIL PROTECTED]]On Behalf Of Peter Dimov

 
> Optional does not have pointer semantics. Two optionals can 
> never alias each
> other. "Consistent with pointer semantics" doesn't make 
> sense. Optional is
> not a pointer. Don't try to make it into one; you'll arrive 
> at shared_ptr.
> ;-)

:-) true. But it also does not have container semantics either.
I prefered your analogy with a special valued INT. Given that we
have 
*opt1 == *opt2 
for ordinary value comparisons then

opt1 == opt2

is purely a test of the two optional's state.

/ikh

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread David Abrahams
"Peter Dimov" <[EMAIL PROTECTED]> writes:

> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>> > Yes, I thought about that, too. But if the current swap semantics are
>> > retained, it should simply be removed. Otherwise optional::swap must
>> > offer at least swap(T&, T&)'s guarantee.
>> >
>> I'm not sure I follow.
>> What are swap(T&, T&) guarantees in general?
>> I thought this depended on the specific type.
>
> True, swap()'s guarantees depend on the type. If T provides a
> nothrow/strong/basic swap, optional::swap should be at least
> nothrow/strong/basic, respectively. I think that this can be done provided
> that T(T const &) is strong and T::~T is nothrow.

I'm confused by this. A constructor pretty much always gives the
strong guarantee if it gives the basic guarantee.

I suppose it could have side-effects...

>> Anyway, as I posted recently, I'm just about to conclude that relational
>> operators
>> could be properly defined as a synonim for: get_pointer(o1) .relop.
>> get_pointer(o2).
>> I found this definition totally consistent with pointer semantics and the
>> implied
>> aliasings.
>
> Optional does not have pointer semantics. Two optionals can never alias each
> other. "Consistent with pointer semantics" doesn't make sense. Optional is
> not a pointer. Don't try to make it into one; you'll arrive at shared_ptr.
> ;-)

As usual, I agree with Peter

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > Yes, I thought about that, too. But if the current swap semantics are
> > retained, it should simply be removed. Otherwise optional::swap must
> > offer at least swap(T&, T&)'s guarantee.
> >
> I'm not sure I follow.
> What are swap(T&, T&) guarantees in general?
> I thought this depended on the specific type.

True, swap()'s guarantees depend on the type. If T provides a
nothrow/strong/basic swap, optional::swap should be at least
nothrow/strong/basic, respectively. I think that this can be done provided
that T(T const &) is strong and T::~T is nothrow.

> Anyway, as I posted recently, I'm just about to conclude that relational
> operators
> could be properly defined as a synonim for: get_pointer(o1) .relop.
> get_pointer(o2).
> I found this definition totally consistent with pointer semantics and the
> implied
> aliasings.

Optional does not have pointer semantics. Two optionals can never alias each
other. "Consistent with pointer semantics" doesn't make sense. Optional is
not a pointer. Don't try to make it into one; you'll arrive at shared_ptr.
;-)

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola

- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 12:18 PM
Subject: Re: [boost] Formal review: Optional library


> Fernando Cacciola said:
> > From: "Peter Dimov" <[EMAIL PROTECTED]>
> >> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> >> > Perhaps this could be called get_pointer() as shared_ptr<> does.
> >>
> >> get_pointer() would be... less objectionable. :-)
> >>
> > This particular free function is precisely intended to decouple this
> > functionality (get a pointer that points to the value) from the class
> > type (optional<> in this case); so it makes sense to be a commonly named
> > free function.
> > But then, get_pointer() is the common name, so it has to be that one.
>
>
> >> bool operator==(optional const & a, optional const & b)
> >> {
> >> if(a.initialized() != b.initialized()) return false;
> >> return a.initialized()? *a == *b: true;
> >> }
> >>
> >> That is, an unitialized optional is equal to an unitialized optional,
> >> and not equal to an initialized one.
> >>
> >> Two initialized optionals are equal when their values compare equal.
> >>
> >> If you think of an optional as a constrained std::vector, you'll
> >> see
> > that
> >> the above semantics correspond to vector<>::operator==.
> >>
> >> The other way of thinking about an optional is that it is capable
> >> of storing all possible values of type T plus an additional value
> > corresponding
> >> to the uninitialized state. In other words, optional can be
> >> thought
> > of
> >> as an integer that can store INT_MIN...INT_MAX+1, with INT_MAX+1 being
> >> interpreted as uninitialized. The above comparison does the right
> >> thing
> > for
> >> this model, too.
> >>
> >> A variant would have the same operator==, too.
> >>
> > Well, this is exactly what William suggested.
> > Still I don't like it.
> > But thanks to William insistance on a sound rationale, I realize now
> > that the real problem
> > is not the personally-odd definition that something is definitely not
> > equal to nothing
> > (instead of undefined); since this definition doesn't look odd to many
> > of you,
> > but the fact that such definition would look ackward with respect to the
> > pointer-like interface.
> >
> > Anyway, as I posted recently, I'm just about to conclude that relational
> > operators
> > could be properly defined as a synonim for: get_pointer(o1) .relop.
> > get_pointer(o2).
> > I found this definition totally consistent with pointer semantics and
> > the implied
> > aliasings.
>
> So, from recent postings it sounds like you've made several more decisions
> on the interface (deep const, relational ops, get_pointer(), explicit
> templated constructor from other optional<> types, anything else?).  Can
> we get you to illustrate the changes and/or republish the documentation
> again?  I think we're finally at a point that everything I brought up has
> been addressed to my satisfaction, but before I drop out of the discussion
> I want to make sure :).
>
Yes. I'm precisely doing it. I'll republish everything ASAP... stay tuned.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread William E. Kempf
Fernando Cacciola said:
> From: "Peter Dimov" <[EMAIL PROTECTED]>
>> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>> > Perhaps this could be called get_pointer() as shared_ptr<> does.
>>
>> get_pointer() would be... less objectionable. :-)
>>
> This particular free function is precisely intended to decouple this
> functionality (get a pointer that points to the value) from the class
> type (optional<> in this case); so it makes sense to be a commonly named
> free function.
> But then, get_pointer() is the common name, so it has to be that one.


>> bool operator==(optional const & a, optional const & b)
>> {
>> if(a.initialized() != b.initialized()) return false;
>> return a.initialized()? *a == *b: true;
>> }
>>
>> That is, an unitialized optional is equal to an unitialized optional,
>> and not equal to an initialized one.
>>
>> Two initialized optionals are equal when their values compare equal.
>>
>> If you think of an optional as a constrained std::vector, you'll
>> see
> that
>> the above semantics correspond to vector<>::operator==.
>>
>> The other way of thinking about an optional is that it is capable
>> of storing all possible values of type T plus an additional value
> corresponding
>> to the uninitialized state. In other words, optional can be
>> thought
> of
>> as an integer that can store INT_MIN...INT_MAX+1, with INT_MAX+1 being
>> interpreted as uninitialized. The above comparison does the right
>> thing
> for
>> this model, too.
>>
>> A variant would have the same operator==, too.
>>
> Well, this is exactly what William suggested.
> Still I don't like it.
> But thanks to William insistance on a sound rationale, I realize now
> that the real problem
> is not the personally-odd definition that something is definitely not
> equal to nothing
> (instead of undefined); since this definition doesn't look odd to many
> of you,
> but the fact that such definition would look ackward with respect to the
> pointer-like interface.
>
> Anyway, as I posted recently, I'm just about to conclude that relational
> operators
> could be properly defined as a synonim for: get_pointer(o1) .relop.
> get_pointer(o2).
> I found this definition totally consistent with pointer semantics and
> the implied
> aliasings.

So, from recent postings it sounds like you've made several more decisions
on the interface (deep const, relational ops, get_pointer(), explicit
templated constructor from other optional<> types, anything else?).  Can
we get you to illustrate the changes and/or republish the documentation
again?  I think we're finally at a point that everything I brought up has
been addressed to my satisfaction, but before I drop out of the discussion
I want to make sure :).

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 9:41 AM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> >
> > Let me check if I followed your logic:
> >
> > optional opt(v) does a 'copy' of the 'v'; it does not hold onto the
> > 'v' itself as if it were given a handle. So it clearly has deep copy
> > semantics.
> > Your argument is that since it has deep copy semantics, it should have
> > deep-constantness
> > too, right?
>
> Right.
>
> "Pointer semantics" means that copies of the pointer refer to the same
> object. This is clearly not the case with optional<> as it contains a
value,
> it doesn't merely point to one. Optional simply does not have pointer
> semantics. It provides a pointer-like interface which may be controversial
> but I'm not convinced that better alternatives exist.
>
This is correct.
See my response to Augustus where I realize that optional<> mixes value and
pointer
semantics on two different parts of the interface.
As I argumented there, in spite of the oddity, the separation is made in
such a way that
there is no -or little- confusion (once you get how it is)

>
> > > > void swap ( optional& rhs ) ;
> > >
> > > Doesn't the standard std::swap do the job, by the way?
> > >
> > With the current implementation, yes, it does.
> > But if optional<> is eventually changed to use an implementation
> > with stronger exception guarantees, wouldn't it require a member swap()?
>
> Yes, I thought about that, too. But if the current swap semantics are
> retained, it should simply be removed. Otherwise optional::swap must
> offer at least swap(T&, T&)'s guarantee.
>
I'm not sure I follow.
What are swap(T&, T&) guarantees in general?
I thought this depended on the specific type.

>
> > > > template inline T* get ( optional const& opt ) ;
> > >
> > > Why the free function?
> > >
> > On the user code I **really** prefer to write: get(opt) instead of
> opt.get()
> > becasue I like to decouple from class types as much as possible.
>
> Free functions with generic names should be avoided.
>
I agree.

> > Perhaps this could be called get_pointer() as shared_ptr<> does.
>
> get_pointer() would be... less objectionable. :-)
>
This particular free function is precisely intended to decouple this
functionality (get a pointer that points to the value) from the class type
(optional<> in this case); so it makes sense to be a commonly named free
function.
But then, get_pointer() is the common name, so it has to be that one.

> > > I think that the comparisons we were discussing as a possible
candidate
> > > required both the initialized states and the held values to match.
> > >
> > > This is consistent with the "optional as a container of zero/one" and
> the
> > > "optional as a value with an additional unitialized state" models.
> > >
> > I don't follow 'exactly'
> > Can you elaborate?
>
> bool operator==(optional const & a, optional const & b)
> {
> if(a.initialized() != b.initialized()) return false;
> return a.initialized()? *a == *b: true;
> }
>
> That is, an unitialized optional is equal to an unitialized optional, and
> not equal to an initialized one.
>
> Two initialized optionals are equal when their values compare equal.
>
> If you think of an optional as a constrained std::vector, you'll see
that
> the above semantics correspond to vector<>::operator==.
>
> The other way of thinking about an optional is that it is capable of
> storing all possible values of type T plus an additional value
corresponding
> to the uninitialized state. In other words, optional can be thought
of
> as an integer that can store INT_MIN...INT_MAX+1, with INT_MAX+1 being
> interpreted as uninitialized. The above comparison does the right thing
for
> this model, too.
>
> A variant would have the same operator==, too.
>
Well, this is exactly what William suggested.
Still I don't like it.
But thanks to William insistance on a sound rationale, I realize now that
the real problem
is not the personally-odd definition that something is definitely not equal
to nothing
(instead of undefined); since this definition doesn't look odd to many of
you,
but the fact that such definition would look ackward with respect to
the pointer-like interface.

Anyway, as I posted recently, I'm just about to conclude that relational
operators
could be properly defined as a synonim for: get_pointer(o1) .relop.
get_pointer(o2).
I found this definition totally consistent with pointer semantics and the
implied
aliasings.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Fernando Cacciola

- Original Message -
From: "Iain K.Hanson" <[EMAIL PROTECTED]>
To: "'Boost mailing list'" <[EMAIL PROTECTED]>
Sent: Thursday, December 12, 2002 8:20 AM
Subject: RE: [boost] Formal review: Optional library


>
>
> > [mailto:[EMAIL PROTECTED]]On Behalf Of Iain K.Hanson
> > Sent: 12 December 2002 10:15
> > To: 'Boost mailing list'
> > Subject: RE: [boost] Formal review: Optional library
> >
> >
> >
> > assert( a == b ) // pointer semantics.
> > if this used value semantics then this would mostly fail and randomly
> > suceeed.
>
> Whoops - brain fade. Yhis would also be true of pointer semantics.
> Maybe this argues Fernando's point that they should not be defined.
> However, given that we already have dereference, it would be nice to
> have the syntacic sugar I described in my previous post.
>
I agree that it would be possible to define relational operators
as a shorthand for get(o1) == get(o2).
I'm not sure of its usefullness, but at least it seems consistent with the
part of the interface with pointer semantics.

Notice that aliasing, i.e. the fact that equaliy implies that optional
values (pointees) are effectively the same _object_ will actually work as
expected, unlike Augustus predicted.
The reason is that with this definition, equality will be true iif both
optionals are
_uninitialized_ or are the _exact same object_:

optional o1 ;
optional o2 ;
(o1 == o2) -> true; and since *o1 and *o2 are undefined, there is no implied
aliasing.

o1.reset(1);
o2.reset(2);
(o1 == o1) -> true, and the implied aliasing that *o1=3 implies *o2==3
holds.

(o1 == o2 ) -> false, so no aliasing is implied.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-12 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
> Let me check if I followed your logic:
>
> optional opt(v) does a 'copy' of the 'v'; it does not hold onto the
> 'v' itself as if it were given a handle. So it clearly has deep copy
> semantics.
> Your argument is that since it has deep copy semantics, it should have
> deep-constantness
> too, right?

Right.

"Pointer semantics" means that copies of the pointer refer to the same
object. This is clearly not the case with optional<> as it contains a value,
it doesn't merely point to one. Optional simply does not have pointer
semantics. It provides a pointer-like interface which may be controversial
but I'm not convinced that better alternatives exist.

> > > void swap ( optional& rhs ) ;
> >
> > Doesn't the standard std::swap do the job, by the way?
> >
> With the current implementation, yes, it does.
> But if optional<> is eventually changed to use an implementation
> with stronger exception guarantees, wouldn't it require a member swap()?

Yes, I thought about that, too. But if the current swap semantics are
retained, it should simply be removed. Otherwise optional::swap must
offer at least swap(T&, T&)'s guarantee.

> > > template inline T* get ( optional const& opt ) ;
> >
> > Why the free function?
> >
> On the user code I **really** prefer to write: get(opt) instead of
opt.get()
> becasue I like to decouple from class types as much as possible.

Free functions with generic names should be avoided.

> Perhaps this could be called get_pointer() as shared_ptr<> does.

get_pointer() would be... less objectionable. :-)

> > I think that the comparisons we were discussing as a possible candidate
> > required both the initialized states and the held values to match.
> >
> > This is consistent with the "optional as a container of zero/one" and
the
> > "optional as a value with an additional unitialized state" models.
> >
> I don't follow 'exactly'
> Can you elaborate?

bool operator==(optional const & a, optional const & b)
{
if(a.initialized() != b.initialized()) return false;
return a.initialized()? *a == *b: true;
}

That is, an unitialized optional is equal to an unitialized optional, and
not equal to an initialized one.

Two initialized optionals are equal when their values compare equal.

If you think of an optional as a constrained std::vector, you'll see that
the above semantics correspond to vector<>::operator==.

The other way of thinking about an optional is that it is capable of
storing all possible values of type T plus an additional value corresponding
to the uninitialized state. In other words, optional can be thought of
as an integer that can store INT_MIN...INT_MAX+1, with INT_MAX+1 being
interpreted as uninitialized. The above comparison does the right thing for
this model, too.

A variant would have the same operator==, too.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Formal review: Optional library

2002-12-12 Thread Iain K.Hanson


> [mailto:[EMAIL PROTECTED]]On Behalf Of Iain K.Hanson
> Sent: 12 December 2002 10:15
> To: 'Boost mailing list'
> Subject: RE: [boost] Formal review: Optional library
> 
> 
> 
> assert( a == b ) // pointer semantics.
> if this used value semantics then this would mostly fail and randomly
> suceeed.

Whoops - brain fade. Yhis would also be true of pointer semantics.
Maybe this argues Fernando's point that they should not be defined.
However, given that we already have dereference, it would be nice to
have the syntacic sugar I described in my previous post.

/ikh
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Formal review: Optional library

2002-12-12 Thread Iain K.Hanson


> [mailto:[EMAIL PROTECTED]]On Behalf Of William E. Kempf
> Sent: 11 December 2002 20:42
>

[ snip ...]

>
> I agree with this.  The optional<> concept takes some type and extends
> it's possible values to include a new "uninitialized" value.  It seems
> wholly logical to me for this:
>
> optional a();
> optional b();
> optional c(1);
> optional d(2);
> optional e(2);
>
> assert(a == b);  // both uninitialized
> assert(a != c);  // one uninitialized
> assert(c != d);  // both initialized to different values
> assert(d == 3);  // both initialized to same value

I don't agree with this. It seems to be mixing both pointer and value
semantics.

assert( a == b ) // pointer semantics.
if this used value semantics then this would mostly fail and randomly
suceeed.

given that we can already do *c != *d then if relationl operators are to
add any value, they would need to be:

assert(a == b);  // both uninitialized
assert(a != c);  // one uninitialized
assert(c == d);  // both initialized

>
> However, not all types wrapped in optional will be
> comparable... so,
> I'm not adverse to leaving comparison operators out just to
> simplify the
> interface.  I just don't agree with the current rationale.

If that is the compromise that is required, I can live with it.
but it would be nice to have them as I have defined above as
we already have the value operators and it would be a short hand
for:

 get( c ) == get ( d )
or
 c.get( ) == d.get( )

/ikh

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 6:45 PM
Subject: Re: [boost] Formal review: Optional library


> David Abrahams said:
> > "Peter Dimov" <[EMAIL PROTECTED]> writes:
> >
> >> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> >> [...]
> >>> (1) deep-constantness:
> >>>
> >>> I Followed David Abraham's suggestion and decoupled
> >>> constantness of the optional<> object with that of
> >>> the value being wrapped.
> >>> This is how pointers and most smart pointers work, so
> >>> the pointer semantic should suffice to explain this behaviour.
> >>
> >> Hm. Did Dave really suggest that? :-)
> >
> > Not exactly.  I said that deep constness is inconsistent with a
> > pointer-oriented interface.
> >
> >> To reiterate, my opinion is that deep constness is much more
> >> appropriate for optional<>. Constness and copying go hand in hand:
> >> deep copy corresponds to deep constness, and shallow copy
> >> corresponds to shallow constness.  Optional<> does a deep copy. Even
> >> smart pointers that do deep copy use deep const.
> >
> > Oh, well yeah.  There are some smart pointers that do that.  I've
> > never touched one.  So maybe a "deep" optional with a smart pointer
> > interface is not such an odd beast.
>
> I'd have to agree with the analysis and would lobby for deep const as
> well, after this rationale.
>
OK.

> To my mind that leaves two things left undecided (by me, not necessarily
> by the group at large).  One is whether or not to include comparison
> operators.  I guess I'm currently undecided and would like to hear some
> rationale for both sides.
>
OK.
We can discuss this further.
Notice that Tanton considered relation operators to mimic pointers, meaning
that (opt1==opt2) should not compare values as if it were (*opt1 == *opt2);
even if both are initialized.
In the case of optional<>, however, there is not really a notion of 'pointer
value'; being the 'initialization state' the closest concept.
But I shown that if relation operators were to compare only initialization
states they would still be wrong.

So, I have a new argument against directing comparing optional<>:

even if comparison against one uninitialized value could be defined as a
definitive false, such
a comparison, with a syntax: (opt1==opt2), comparing values ( just as if it
were (*opt1==*opt2))
breaks pointer semantics.

> The other is the templated constructor from other optionals.  I still
> think this is important, but not as currently specified.  The current
> conversion only from const versions is not so important since we'll have
> "deep const".  But conversion from other types, such as optional to
> optional would be more complex than it should be with out this.  An
> implicit constructor would obviously be bad here, but an explicit one
> should probably be included.
>
Interesting point.
Being explicit it won't be dangerous, and it might be useful indeed.
I think I'll add it.

BTW: I've noticed after thinking about Peter's argument about
deep-copy/deep-constantness that, indeed,
due to the deep-copy semantics, optional cannot really be properly
supported, since, for instance,
reset( T const& ) cannot be provided.
Therefore, I think optional should not be supported; and
deep-constantness used instead.

Fernando Cacciola



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 5:47 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> [...]
> > (1) deep-constantness:
> >
> > I Followed David Abraham's suggestion and decoupled
> > constantness of the optional<> object with that of
> > the value being wrapped.
> > This is how pointers and most smart pointers work, so
> > the pointer semantic should suffice to explain this behaviour.
>
> Hm. Did Dave really suggest that? :-)
>
Sort of.
He said that if optional<> is supposed to offer pointer semantics
then it should not provide deep constantness simply because pointers
don't do that.

> To reiterate, my opinion is that deep constness is much more appropriate
for
> optional<>. Constness and copying go hand in hand: deep copy corresponds
to
> deep constness, and shallow copy corresponds to shallow constness.
> Optional<> does a deep copy. Even smart pointers that do deep copy use
deep
> const.
>
Good point.

Let me check if I followed your logic:

optional opt(v) does a 'copy' of the 'v'; it does not hold onto the
'v' itself as if it were given a handle. So it clearly has deep copy
semantics.
Your argument is that since it has deep copy semantics, it should have
deep-constantness
too, right?

>
> > template
> > class optional
> > {
>
> [...]
>
> > void swap ( optional& rhs ) ;
>
> Doesn't the standard std::swap do the job, by the way?
>
With the current implementation, yes, it does.
But if optional<> is eventually changed to use an implementation
with stronger exception guarantees, wouldn't it require a member swap()?
That's the reason I put it there.

> [...]
>
> > } ;
> >
> > template inline T* get ( optional const& opt ) ;
>
> Why the free function?
>
On the user code I **really** prefer to write: get(opt) instead of opt.get()
becasue I like to decouple from class types as much as possible.
Perhaps this could be called get_pointer() as shared_ptr<> does.

> >
> > template inline void swap ( optional& x, optional& y ) ;
>
> [...]
> > This is utterly important now that is has safe_bool,
> > because IMO, Tanton Gibbs interpretation is correct;
> > given safe_bool:
> >
> > optional opt0 ;
> > optional opt1 ;
> >
> > (opt0 == 0 ) // true
> > (opt1 == 0 ) // true
> >
> > therefore
> >
> > (opt0 == opt1) HAS TO BE TRUE.
> >
> >
> > If the comparison above is properly understood,
> > that is, if it is clear that the initialized states
> > are being compared and not the values, then there is
> > no problem, but considering that:
> >
> > optional opt0(1);
> > optional opt1(2);
> > (opt0 == opt1) // true
> >
> > is also true even though the values are different,
> > I think that allowing direct comparions will
> > create unneccesary confusion.
>
> I think that the comparisons we were discussing as a possible candidate
> required both the initialized states and the held values to match.
>
> This is consistent with the "optional as a container of zero/one" and the
> "optional as a value with an additional unitialized state" models.
>
I don't follow 'exactly'
Can you elaborate?

Fernando Cacciola


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread William E. Kempf
David Abrahams said:
> "Peter Dimov" <[EMAIL PROTECTED]> writes:
>
>> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>> [...]
>>> (1) deep-constantness:
>>>
>>> I Followed David Abraham's suggestion and decoupled
>>> constantness of the optional<> object with that of
>>> the value being wrapped.
>>> This is how pointers and most smart pointers work, so
>>> the pointer semantic should suffice to explain this behaviour.
>>
>> Hm. Did Dave really suggest that? :-)
>
> Not exactly.  I said that deep constness is inconsistent with a
> pointer-oriented interface.
>
>> To reiterate, my opinion is that deep constness is much more
>> appropriate for optional<>. Constness and copying go hand in hand:
>> deep copy corresponds to deep constness, and shallow copy
>> corresponds to shallow constness.  Optional<> does a deep copy. Even
>> smart pointers that do deep copy use deep const.
>
> Oh, well yeah.  There are some smart pointers that do that.  I've
> never touched one.  So maybe a "deep" optional with a smart pointer
> interface is not such an odd beast.

I'd have to agree with the analysis and would lobby for deep const as
well, after this rationale.

To my mind that leaves two things left undecided (by me, not necessarily
by the group at large).  One is whether or not to include comparison
operators.  I guess I'm currently undecided and would like to hear some
rationale for both sides.

The other is the templated constructor from other optionals.  I still
think this is important, but not as currently specified.  The current
conversion only from const versions is not so important since we'll have
"deep const".  But conversion from other types, such as optional to
optional would be more complex than it should be with out this.  An
implicit constructor would obviously be bad here, but an explicit one
should probably be included.

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "Tanton Gibbs" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 5:22 PM
Subject: Re: [boost] Formal review: Optional library


> > optional opt0(1);
> > optional opt1(2);
> > (opt0 == opt1) // true
>
> I would not have any problem with this returning false.
>
This would return false only if it compares values,
but it would return true if it compares initialization states.

I see that (opt0==opt1) makes sense to compare true when
both are uninitialized if this comparison is defined
to compare initialization states.

However, William suggests that relational operators for optional can be
defined to compare values, not initialization states, with just the
particular
clause that comparing a value against nothing (for equality) yields false.
This is the model followed by NANs, and is perfectly well defined.
My problem is that even though it is well defined, and known  think,
I just don't find this definition usefull; I don't want this comparison to
yield false,
I want it to be undefined.
Anyway, I still owe William a concrete example to show why this definition
is not usefull; though I would conversely like to see an example were it is.


>  In the normal ptr
> world:
> char c, d;
> char* p, *q;
> p = &c;
> q = &d;
>
> if( p == q ) // false
>
> People expect it to compare memory locations, not initialization status.
>
Right, and memory locations have nothing to do with pointee-values:

char c = 1 :
char d = 1 ;
char* p = &c, *q = &d;
( p == q ) // false even though (*p == *q) is true

char e = 1 :
char f = 2 ;
char* r = &r, *s = &f;
( r == s ) // still false even though (*r == *s) is false

As you can see, relational operators in optional, if they follow the
definition suggested by William, break pointer semantics
because they would be comparing values (pointee) which is
totally unlike pointers (you don't compare pointee values when comparing
pointers)

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread William E. Kempf

David Abrahams said:
> "William E. Kempf" <[EMAIL PROTECTED]> writes:
>
>> Tanton Gibbs said:
 optional opt0(1);
 optional opt1(2);
 (opt0 == opt1) // true
>>>
>>> I would not have any problem with this returning false.  In the
>>> normal ptr world:
>>> char c, d;
>>> char* p, *q;
>>> p = &c;
>>> q = &d;
>>>
>>> if( p == q ) // false
>>>
>>> People expect it to compare memory locations, not initialization
>>> status. Therefore, I would have no problem with operator== returning
>>> true only if both
>>> were uninitialized.
>>
>> I agree with this.  The optional<> concept takes some type and extends
>> it's possible values to include a new "uninitialized" value.  It seems
>> wholly logical to me for this:
>>
>> optional a();
>> optional b();
>> optional c(1);
>> optional d(2);
>> optional e(2);
>>
>> assert(a == b);  // both uninitialized
>> assert(a != c);  // one uninitialized
>> assert(c != d);  // both initialized to different values
>> assert(d == 3);  // both initialized to same value
> "2?"--^

Actually, "e"... the keys were close enough together for my small fingers
to smash the wrong one ;).

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Tanton Gibbs
> optional a();
> optional b();
> optional c(1);
> optional d(2);
> optional e(2);
>
> assert(a == b);  // both uninitialized
> assert(a != c);  // one uninitialized
> assert(c != d);  // both initialized to different values
> assert(d == 3);  // both initialized to same value
>
> However, not all types wrapped in optional will be comparable... so,
> I'm not adverse to leaving comparison operators out just to simplify the
> interface.  I just don't agree with the current rationale.
>
> William E. Kempf

I assume you mean
assert( d == optional<>(2) );

However, I still think this is incorrectconsider
char c = 'c', d = 'c';
char *p, *q;
p = &c; q = &d;
assert( p != q );

It doesn't matter what their values are...it is the addresses of those
values that matter.

Therefore, I think that, if optional<> is a smart ptr,
assert( d != optional<>(2) );
must be true.  Only if two elements are uninitialized should they be
equal...otherwise, we must compare their "pointer" values, not their element
values.

Tanton

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Joel de Guzman

- Original Message - 
From: "Fernando Cacciola" <[EMAIL PROTECTED]>

> > And my point, again, is that you can easily add an *easier* API
> > that does exactly like your optional API *over* the variant. My
> > concern is primarily about redundancy of code. I don't see any
> > reason why the optional and the variant can't share the same
> > underlying infrastructure.
> >
> Aha!
> You just meant that optional<>, with a given interface, could be implemented
> on top of variant_t?
> Yes, definitely.
> In fact, if optional<> is accepted, when we have variant<>, it is quite
> likely that I do just that.

Exactly. 

You might have missed it but I actually voted "yes" for acceptance.
I have needs for the variant (Hey variant guys where are you?)
and your optional class might fill that need now. I'm sure Doug 
knows why :-)

As an aside, you might want to consider continuing and actually 
implementing a variant (at least to awaken the variant guys, or 
maybe not if you get there first). I think that will be a logical next-step 
to take. 

See http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Variant

Cheers,
Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 5:49 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > >
> > > You should consider providing operator<<(std::ostream&, optional),
too.
> > >
> > Interesting...
> > The idea is that if the optional is uninitialized, it outputs something
> like
> > "[NULL]",
> > else forwards to T::operator <<(), right?
> >
> > I agree it is usefull, but I'm not sure if it should be provided by the
> > library itself.
>
> If you have a conversion to a "member pointer bool", you have to provide a
> reasonable operator<<, too, otherwise the standard operator<<(ostream&,
> bool) is used. :-)
>
Good point!

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread David Abrahams
"Peter Dimov" <[EMAIL PROTECTED]> writes:

> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> [...]
>> (1) deep-constantness:
>>
>> I Followed David Abraham's suggestion and decoupled
>> constantness of the optional<> object with that of
>> the value being wrapped.
>> This is how pointers and most smart pointers work, so
>> the pointer semantic should suffice to explain this behaviour.
>
> Hm. Did Dave really suggest that? :-)

Not exactly.  I said that deep constness is inconsistent with a
pointer-oriented interface.

> To reiterate, my opinion is that deep constness is much more
> appropriate for optional<>. Constness and copying go hand in hand:
> deep copy corresponds to deep constness, and shallow copy
> corresponds to shallow constness.  Optional<> does a deep copy. Even
> smart pointers that do deep copy use deep const.

Oh, well yeah.  There are some smart pointers that do that.  I've
never touched one.  So maybe a "deep" optional with a smart pointer
interface is not such an odd beast.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread David Abrahams
"William E. Kempf" <[EMAIL PROTECTED]> writes:

> Tanton Gibbs said:
>>> optional opt0(1);
>>> optional opt1(2);
>>> (opt0 == opt1) // true
>>
>> I would not have any problem with this returning false.  In the normal
>> ptr world:
>> char c, d;
>> char* p, *q;
>> p = &c;
>> q = &d;
>>
>> if( p == q ) // false
>>
>> People expect it to compare memory locations, not initialization status.
>> Therefore, I would have no problem with operator== returning true only
>> if both
>> were uninitialized.
>
> I agree with this.  The optional<> concept takes some type and extends
> it's possible values to include a new "uninitialized" value.  It seems
> wholly logical to me for this:
>
> optional a();
> optional b();
> optional c(1);
> optional d(2);
> optional e(2);
>
> assert(a == b);  // both uninitialized
> assert(a != c);  // one uninitialized
> assert(c != d);  // both initialized to different values
> assert(d == 3);  // both initialized to same value
"2?"--^ 

BTW, that's a container-like interface. I have no problem with that,
but then I'm a bit concerned about the pointer-like interface to the
rest of the class.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> >
> > You should consider providing operator<<(std::ostream&, optional), too.
> >
> Interesting...
> The idea is that if the optional is uninitialized, it outputs something
like
> "[NULL]",
> else forwards to T::operator <<(), right?
>
> I agree it is usefull, but I'm not sure if it should be provided by the
> library itself.

If you have a conversion to a "member pointer bool", you have to provide a
reasonable operator<<, too, otherwise the standard operator<<(ostream&,
bool) is used. :-)

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "Joel de Guzman" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 5:18 PM
Subject: Re: [boost] Formal review: Optional library


> - Original Message -
> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
>
> > > It's trivial to make that a free function like get. Or further, to
make
> > > a subset API for optional.
> > >
> > You can certainly do the same with variant. The point is that with
> > optional<> it is *easier*.
> > With optional<> you don't need to specify the type of the wrapped value
all
> > the time as with variant; and you don't need to explicitly test if the
> > variant holds a "nil_t" in order to see if it is initialized.
>
> And my point, again, is that you can easily add an *easier* API
> that does exactly like your optional API *over* the variant. My
> concern is primarily about redundancy of code. I don't see any
> reason why the optional and the variant can't share the same
> underlying infrastructure.
>
Aha!
You just meant that optional<>, with a given interface, could be implemented
on top of variant_t?
Yes, definitely.
In fact, if optional<> is accepted, when we have variant<>, it is quite
likely that I do just that.

Fernando Cacciola



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
[...]
> (1) deep-constantness:
>
> I Followed David Abraham's suggestion and decoupled
> constantness of the optional<> object with that of
> the value being wrapped.
> This is how pointers and most smart pointers work, so
> the pointer semantic should suffice to explain this behaviour.

Hm. Did Dave really suggest that? :-)

To reiterate, my opinion is that deep constness is much more appropriate for
optional<>. Constness and copying go hand in hand: deep copy corresponds to
deep constness, and shallow copy corresponds to shallow constness.
Optional<> does a deep copy. Even smart pointers that do deep copy use deep
const.

> template
> class optional
> {

[...]

> void swap ( optional& rhs ) ;

Doesn't the standard std::swap do the job, by the way?

[...]

> } ;
>
> template inline T* get ( optional const& opt ) ;

Why the free function?

>
> template inline void swap ( optional& x, optional& y ) ;

[...]
> This is utterly important now that is has safe_bool,
> because IMO, Tanton Gibbs interpretation is correct;
> given safe_bool:
>
> optional opt0 ;
> optional opt1 ;
>
> (opt0 == 0 ) // true
> (opt1 == 0 ) // true
>
> therefore
>
> (opt0 == opt1) HAS TO BE TRUE.
>
>
> If the comparison above is properly understood,
> that is, if it is clear that the initialized states
> are being compared and not the values, then there is
> no problem, but considering that:
>
> optional opt0(1);
> optional opt1(2);
> (opt0 == opt1) // true
>
> is also true even though the values are different,
> I think that allowing direct comparions will
> create unneccesary confusion.

I think that the comparisons we were discussing as a possible candidate
required both the initialized states and the held values to match.

This is consistent with the "optional as a container of zero/one" and the
"optional as a value with an additional unitialized state" models.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread William E. Kempf
Tanton Gibbs said:
>> optional opt0(1);
>> optional opt1(2);
>> (opt0 == opt1) // true
>
> I would not have any problem with this returning false.  In the normal
> ptr world:
> char c, d;
> char* p, *q;
> p = &c;
> q = &d;
>
> if( p == q ) // false
>
> People expect it to compare memory locations, not initialization status.
> Therefore, I would have no problem with operator== returning true only
> if both
> were uninitialized.

I agree with this.  The optional<> concept takes some type and extends
it's possible values to include a new "uninitialized" value.  It seems
wholly logical to me for this:

optional a();
optional b();
optional c(1);
optional d(2);
optional e(2);

assert(a == b);  // both uninitialized
assert(a != c);  // one uninitialized
assert(c != d);  // both initialized to different values
assert(d == 3);  // both initialized to same value

However, not all types wrapped in optional will be comparable... so,
I'm not adverse to leaving comparison operators out just to simplify the
interface.  I just don't agree with the current rationale.

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 2:22 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> [...]
> > Conclusion: I will adopt William's reset, leaving operator*() return
> > a reference to the optional value *only* if it is initialized
> > (independently of whether opt is const or not).
> >
> > Therefore, the proxy is not needed. And so value() isn't needed either.
> >
> > (B)
> > Since most reviewers wanted it, I will add a safe_bool idiom, which will
> > allow
> > conditional expressions like:
> >
> > if ( opt )
> > if ( opt == 0 )
> > if ( opt != 0 )
>
> Can you please update the documentation to reflect the changes? I want to
> vote on the revised version. ;-)
>
Yes, but first look at my last post where I show the new interface entirely.
If that is more or less OK I'll update the documentation in order to
continue with the review.


> > However, I'm still unconvinced that uninitialized optionals should
compare
> > false,
> > and even though, you can always compare optional values (via operator*),
> so
> > I see no benefit in defining relational operators directly (thus these
> > operators
> > will be poisoned)
>
> I think that the proposed comparisons make a lot of sense.
>
Just to make sure I understand what you're saying:
Do you agree about having comparisons undefined for optionals directly
and only defined for optional values (i.e. *opt1==*opt2)?

>
> You should consider providing operator<<(std::ostream&, optional), too.
>
Interesting...
The idea is that if the optional is uninitialized, it outputs something like
"[NULL]",
else forwards to T::operator <<(), right?

I agree it is usefull, but I'm not sure if it should be provided by the
library itself.
A user can define a sort of to_string() with whatever output he wants for
uninitialized.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Joel de Guzman

- Original Message - 
From: "William E. Kempf" <[EMAIL PROTECTED]>

> >> It's trivial to make that a free function like get. Or further, to
> >> make a subset API for optional.
> >>
> > You can certainly do the same with variant. The point is that with
> > optional<> it is *easier*.
> > With optional<> you don't need to specify the type of the wrapped value
> > all the time as with variant; and you don't need to explicitly test if
> > the variant holds a "nil_t" in order to see if it is initialized.
> 
> To add my own 2 cents on why we should have optional<> instead of just
> relying on variant is along the same lines as Fernando is trying
> to convey here.  A std::pair provides all the functionality
> you'd need for a "point" type in a GUI framework, but we'd still want to
> have a point type (which may be implemented in terms of std::pair int>) in order to bring the syntax more in line with domain we're dealing
> with.  The exact same thing applies to optional and variant.
> 
> The argument about optimizing POD cases is less compelling.  Even if the
> optimization was considered necessary, I'd think you could provide it with
> the variant as well (though it would be a trickier
> implementation).

Oh don't get me wrong. I vote to have an optional. Again, my point is 
that it should be noted that we can easily write a thin API over the 
variant that way, we will avoid redundancy of code. Yet of course,
that would have to be in the future since we do not have a variant
yet.

Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Tanton Gibbs
> optional opt0(1);
> optional opt1(2);
> (opt0 == opt1) // true

I would not have any problem with this returning false.  In the normal ptr
world:
char c, d;
char* p, *q;
p = &c;
q = &d;

if( p == q ) // false

People expect it to compare memory locations, not initialization status.
Therefore, I would have no problem with operator== returning true only if
both
were uninitialized.

Tanton

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Joel de Guzman
- Original Message - 
From: "Fernando Cacciola" <[EMAIL PROTECTED]>


> > It's trivial to make that a free function like get. Or further, to make
> > a subset API for optional.
> >
> You can certainly do the same with variant. The point is that with
> optional<> it is *easier*.
> With optional<> you don't need to specify the type of the wrapped value all
> the time as with variant; and you don't need to explicitly test if the
> variant holds a "nil_t" in order to see if it is initialized.

And my point, again, is that you can easily add an *easier* API
that does exactly like your optional API *over* the variant. My
concern is primarily about redundancy of code. I don't see any
reason why the optional and the variant can't share the same 
underlying infrastructure.

Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola
Based on the coments made by reviewers, this is the new interface:

template
class optional
{
optional () ;

explicit optional ( T const& val ) ;

optional ( optional const& rhs ) ;

~optional() ;

// This is provided ONLY to allow implicit conversions from
// optional to optional.
// It compiles only if remove_const::type == U.
template optional ( optional const& non_const_rhs ) ;

optional& operator= ( optional const& rhs ) ;

void swap ( optional& rhs ) ;

// Uninitializes the optional.
void reset() ;

// Initialied the optional (even if it was uninitialized)
void reset ( T const& val ) ;

T* get() const ;

T* operator->() const ;

T& operator *() const ;

typedef T* (this_type::*unspecified_bool_type)();
operator unspecified_bool_type() const ;

bool operator!() const { return !m_initialized ; }

// Disallow direct comparisons between optionals.
friend void operator == ( this_type const&, this_type const& ) ;
friend void operator != ( this_type const&, this_type const& ) ;
} ;

template inline T* get ( optional const& opt ) ;

template inline void swap ( optional& x, optional& y ) ;



This interface settles two issues that were still open:

(1) deep-constantness:

I Followed David Abraham's suggestion and decoupled
constantness of the optional<> object with that of
the value being wrapped.
This is how pointers and most smart pointers work, so
the pointer semantic should suffice to explain this behaviour.

I did added a special template ctor which allows implicit
conversions from optional to optional.

(2) Comparisons.
I'm still holding onto the decision to disallow direct comparison of
optional objects in favor of direction comparison of optional values:
That is, you cannot write:

if ( optA == optB )

and you have to write:

if ( *optA == *optB )

instead.

This is utterly important now that is has safe_bool,
because IMO, Tanton Gibbs interpretation is correct;
given safe_bool:

optional opt0 ;
optional opt1 ;

(opt0 == 0 ) // true
(opt1 == 0 ) // true

therefore

(opt0 == opt1) HAS TO BE TRUE.


If the comparison above is properly understood,
that is, if it is clear that the initialized states
are being compared and not the values, then there is
no problem, but considering that:

optional opt0(1);
optional opt1(2);
(opt0 == opt1) // true

is also true even though the values are different,
I think that allowing direct comparions will
create unneccesary confusion.

If this interface is OK so far I'll update the code and the documention.

Q: Should I reflect this changes during the review?
 The new interface is somewhat different so it affect the rest of the
review.

Fernando Cacciola


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola
- Original Message -
From: "David Abrahams" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 12:46 PM
Subject: Re: [boost] Formal review: Optional library


> "Fernando Cacciola" <[EMAIL PROTECTED]> writes:
>
> Why do you think aligned_storage will be any less-efficient than T
> when T is a POD?
>
> > If you still don't see it I can show you the typical machine
> > generated code for both implementations for operator*().
>
> I'm not surprised the non-POD version is slower as long as you're
> storing a separate pointer. If you use the static_cast form I show
> above, there's no reason for it to be any worse, AFAICT.
>
Well, I actually changed the implementation of pointer_based_optional<>
to use the static_cast<> directy from the aligned_storage, and
beyond any doubts, it is **exactly** as efficient
as the value-based implementation, just like you (and Joel) said.

In fact, after some thinking it was clear that the extra pointer data member
was introducing an additional !unnecesary! indirection.
Thus, the POD optimization was just needed becasue the NonPOD implementation
was plain wrong :-)

There is no need for two implementations any more!

Thanks Joel and David!

Fernando Cacciola


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Tanton Gibbs
> However, I'm still unconvinced that uninitialized optionals should compare
> false,
> and even though, you can always compare optional values (via operator*),
so
> I see no benefit in defining relational operators directly (thus these
> operators
> will be poisoned)

Shouldn't unitialized optionals compare true?  i.e.,

optional x = optional();
optional y = optional();

if( x == 0 ) {
  // this is obviously true
}

if( y == 0 ) {
  // this is obviously true
}

therefore,
if( x == y ) {
  // this should obviously be true
}

Tanton

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 2:00 PM
Subject: Re: [boost] Formal review: Optional library


>
> [snipped]
>
> I like what this is sounding like, but think I have a few more things to
> say.  Before I do so, however, I'd like to see precisely what the no
> interface looks like.  You don't have to repeat the semantic descriptions,
> just show us the public interface.
I'm working on it.

>  There are a few things you've said
> here that aren't totally clear with out this.  For instance, does
> "uninitialize()" become "reset()"?
Exactly.

> What about the issue of
> "deep-constness"?
>
I'm working on it...

I'm also thinking abut the lack of assignment as you suggested.

(There is a very good chance that I end up entirely adopting your
interface.. but I'm considering things one by one)

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
[...]
> Conclusion: I will adopt William's reset, leaving operator*() return
> a reference to the optional value *only* if it is initialized
> (independently of whether opt is const or not).
>
> Therefore, the proxy is not needed. And so value() isn't needed either.
>
> (B)
> Since most reviewers wanted it, I will add a safe_bool idiom, which will
> allow
> conditional expressions like:
>
> if ( opt )
> if ( opt == 0 )
> if ( opt != 0 )

Can you please update the documentation to reflect the changes? I want to
vote on the revised version. ;-)

> However, I'm still unconvinced that uninitialized optionals should compare
> false,
> and even though, you can always compare optional values (via operator*),
so
> I see no benefit in defining relational operators directly (thus these
> operators
> will be poisoned)

I think that the proposed comparisons make a lot of sense.

You should consider providing operator<<(std::ostream&, optional), too.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread William E. Kempf

Fernando Cacciola said:
> These are some conclusions from the review so far:
>
> (A)
> There is particular (mis) feature in optional which is wrongly
> documented (as Peter and William showed me), but
> which is also incorrect.
>
> The expression
>
> *opt=x;
>
> is currently always well defined regardless the initialization state of
> 'opt'.
> If 'opt' is uninitialized, it initializes it to 'x'.
> If 'opt' is initialized, it changes its value to 'x'.
>
> This is the exact same behaviour that William suggested be provided by
> reset( T const& ) ;
>
> However, the documentation is wrong; but partially because the semantic
> of operator*()
> as originally designed is itself wrong.
> If *opt appears as an rvalue instead of an lvalue, the result is
> undefined:
>
> x=*opt; // undefined if opt is uninitialized.
>
> So there is indeed an assymetry.
>
> Furthermore, being able to change the value of an optional
> regardless its initialization state is indeed a good idea,
> but doing it through operator*() does not map truly
> to pointer semantics since you can't do that with a pointer.
> That is, my original design that allows *opt=x to be defined
> even if 'opt' is uninitialized is actually breaking pointer
> semantics.
>
> Conclusion: I will adopt William's reset, leaving operator*() return a
> reference to the optional value *only* if it is initialized
> (independently of whether opt is const or not).
>
> Therefore, the proxy is not needed. And so value() isn't needed either.
>
> (B)
> Since most reviewers wanted it, I will add a safe_bool idiom, which will
> allow
> conditional expressions like:
>
> if ( opt )
> if ( opt == 0 )
> if ( opt != 0 )
>
> Having a safe_bool idiom maked 'initialized()' unnecesary, so it will be
> removed.
>
> However, I'm still unconvinced that uninitialized optionals should
> compare false,
> and even though, you can always compare optional values (via operator*),
> so I see no benefit in defining relational operators directly (thus
> these operators
> will be poisoned)

I like what this is sounding like, but think I have a few more things to
say.  Before I do so, however, I'd like to see precisely what the no
interface looks like.  You don't have to repeat the semantic descriptions,
just show us the public interface.  There are a few things you've said
here that aren't totally clear with out this.  For instance, does
"uninitialize()" become "reset()"?  What about the issue of
"deep-constness"?

Thanks,

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola
These are some conclusions from the review so far:

(A)
There is particular (mis) feature in optional which is wrongly
documented (as Peter and William showed me), but
which is also incorrect.

The expression

*opt=x;

is currently always well defined regardless the initialization state of
'opt'.
If 'opt' is uninitialized, it initializes it to 'x'.
If 'opt' is initialized, it changes its value to 'x'.

This is the exact same behaviour that William suggested be provided by
reset( T const& ) ;

However, the documentation is wrong; but partially because the semantic of
operator*()
as originally designed is itself wrong.
If *opt appears as an rvalue instead of an lvalue, the result is undefined:

x=*opt; // undefined if opt is uninitialized.

So there is indeed an assymetry.

Furthermore, being able to change the value of an optional
regardless its initialization state is indeed a good idea,
but doing it through operator*() does not map truly
to pointer semantics since you can't do that with a pointer.
That is, my original design that allows *opt=x to be defined
even if 'opt' is uninitialized is actually breaking pointer
semantics.

Conclusion: I will adopt William's reset, leaving operator*() return
a reference to the optional value *only* if it is initialized
(independently of whether opt is const or not).

Therefore, the proxy is not needed. And so value() isn't needed either.

(B)
Since most reviewers wanted it, I will add a safe_bool idiom, which will
allow
conditional expressions like:

if ( opt )
if ( opt == 0 )
if ( opt != 0 )

Having a safe_bool idiom maked 'initialized()' unnecesary, so it will be
removed.

However, I'm still unconvinced that uninitialized optionals should compare
false,
and even though, you can always compare optional values (via operator*), so
I see no benefit in defining relational operators directly (thus these
operators
will be poisoned)

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread David Abrahams
"Fernando Cacciola" <[EMAIL PROTECTED]> writes:

> - Original Message -
> From: "David Abrahams" <[EMAIL PROTECTED]>
> To: "Boost mailing list" <[EMAIL PROTECTED]>
> Sent: Tuesday, December 10, 2002 10:00 PM
> Subject: Re: [boost] Formal review: Optional library
>
>
>> "Fernando Cacciola" <[EMAIL PROTECTED]> writes:
>>
>>
>> > I still don't like to think of optional<> as a container, so I still
>> > don't like this reset.
>>
>> Do you really think of auto_ptr and shared_ptr as containers? They
>> seem to have little or nothing in common with any of the standard
>> containers.
>>
> OK.
> After further thinking I agree that optional<> is as much as a container
> as a smart pointer -not much really-, meaning that you pass a value which
> is contained within the wrapper and which you can access it.

Unfortunately, I also agree with Peter Dimov's analysis of the ways in
which optional<> /is/ like a container.  I just meant that the current
_interface_ to optional<>, auto_ptr<>, and shared_ptr<> has nothing in
common with a container's interface.  Sorry to make this difficult.

>> > I'm not sure what would be effect of removing deep-constantness.
>> > It would definitely allow the leaner interface you are proposing,
>>
>> Well, deep-constantness is utterly inconsistent with the pointer-like
>> semantics you claim to be implementing.  A pointer-ish optional
>> component is a fine idea, but why not follow through all the way with
>> the idiom?
>>
> How is deep-constantness utterly incosistent with pointer-like semantics?

typedef T* ptr;
T x;
ptr const p = &x;
T y = *p = x;  // constness of p does not affect mutability of referent

If you think deep constness is important, go with a container-like
interface.  Mixing idioms, especially very familiar ones, is
confusing.

>> > This is a possibility.
>> > I could accept something like this, though I constantly see
>> > people complaining about lack of deep constantness on wrappers like
>> > optional<>
>> > What do others think?
>>
>> Is it a wrapper or a pointer?
>>
> Is a wrapper which acts partially like a pointer.

What I said before about mixing idioms, again.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread William E. Kempf

Fernando Cacciola said:
> From: "Joel de Guzman" <[EMAIL PROTECTED]>
>> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>>
>> > > Hmmm, I'm not sure if I agree with this. T can very well be
>> > > uninitialized in the variant when nil_t is in effect. Then
>> > > nil_t can just be struct nil_t {}; which costs nothing to
>> initialize. Why is optional "more handy" in this regard?
>> > >
>> > Because it has an interface that makes it easier to deal with its
> possibly
>> > uninitialized state:
>> >
>> > optional opt ;
>> > int x = *opt ; // Oops! opt is uninitialied. In debug this is an
> assertion
>> > failure, in release, a core-dump.
>> >
>> > *opt = 3 ; // initializes it.
>> >
>> > if ( int* x = get(opt) )
>> >   some(*x)
>>
>> But of course you also have that interface with the variant.
>> Example:
>>
>>  if (p = variant_cast(pvar))
>>  ...initialized
>>  else
>> ...uninitialized
>>
>> or...
>>
>>   int n = variant_cast(var);
>>   // Oops! var is uninitialied. throws bad_cast
>>
>> It's trivial to make that a free function like get. Or further, to
>> make a subset API for optional.
>>
> You can certainly do the same with variant. The point is that with
> optional<> it is *easier*.
> With optional<> you don't need to specify the type of the wrapped value
> all the time as with variant; and you don't need to explicitly test if
> the variant holds a "nil_t" in order to see if it is initialized.

To add my own 2 cents on why we should have optional<> instead of just
relying on variant is along the same lines as Fernando is trying
to convey here.  A std::pair provides all the functionality
you'd need for a "point" type in a GUI framework, but we'd still want to
have a point type (which may be implemented in terms of std::pair) in order to bring the syntax more in line with domain we're dealing
with.  The exact same thing applies to optional and variant.

The argument about optimizing POD cases is less compelling.  Even if the
optimization was considered necessary, I'd think you could provide it with
the variant as well (though it would be a trickier
implementation).

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread William E. Kempf

Fernando Cacciola said:
> From: "William E. Kempf" <[EMAIL PROTECTED]>
>> Fernando Cacciola said:
>> > Eventually, I realized that value semantics are not really
>> appropiate to deal
>> > with unininitialized states since it blurs the distinction between
>> testing against other values and testing whether it is initialized
>> or not. So I wonder which other semantics would deal with it
>> properly, and pointers poped into my mind quickly.
>>
>> But pointers are just the inverse of the problem above.  Test for
>> validity is bald.
>
> Only if safe_bool isn't used.

Huh?  safe_bool with a pointer?

> But, I'm just about to be convinced to added it, in which case,
> test for validity will look just like it looks like
> for any other smart/bare pointer.
>
>>, while access to the "value" requires some supporting syntax (in
>> this case, operator*).  This leaves users in the exact same scenario
>> where a simple mistake leads to code that compiles but doesn't do what
>> the programmer meant.
>
> Can you give me an example of something that compiles but
> doesn't do what the programmer meant?
> Remeber that currently *opt=x is defined even if opt is uninitialized

bool* p = &some_bool;
if (p) // meant if (*p)

Mistakes similar to this have been made by most C++ programmers.

>> I still don't see the need for the proxy.  The interface I gave could
>> provide "deep-constantness" with out a proxy.  I'm not sure where I
>> stand on whether or not optional<> should provide this, however.
>>
> Right. I mistakenly forgot what the proxy is for...
> it has nothing to do with deep-constantness... o-)
> it is required to support *opt=x for uninitialized optionals, which
> reset 'opt'
> to initilized.

Which according to the documentation would result in undefined behavior ;).

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread David Abrahams
"Fernando Cacciola" <[EMAIL PROTECTED]> writes:

>>
>> There's no need to store p. You can just use
>> static_cast(buffer.address())
>>
> Yes.. I just shown the pointer explicitely.
> The result of the static_cast<> is a pointer, so to obtain a reference (for
> the operator*) you need to 'actually' dereference this poiner.

I have no idea what you're trying to say here.  Could you try again?

>> > OTOH, when T is a POD, so there is no need to bypass its ctor
>> > (since it has a trivial ctor),
>> > the implementation goes like this:
>> >
>> > template
>> > class optional2
>> > {
>> >   optional2 ( T const& val ) v(val) {}
>> >
>> >   T const& operator *() { return val; } // No Dereference here
>> >
>> >   T val ;
>> > } ;
>> >
>> > Anyway, if yoy know how to make an efficient implementation like
>> > the second one with an aligned storage I'll be happy to use it.
>>
>> Why do you think that will be any more efficient than the other
>> implementation when T is POD?
>>
> For POD types: operator*() "directly" returns the value.
> The key is that for POD types, since optional wraps just T (unlike any
> variant) and nothing else, aligned_storage is not required.
> optional<> simply contains a data member of type T, that's all.

Why do you think aligned_storage will be any less-efficient than T
when T is a POD?

> If you still don't see it I can show you the typical machine
> generated code for both implementations for operator*().

I'm not surprised the non-POD version is slower as long as you're
storing a separate pointer. If you use the static_cast form I show
above, there's no reason for it to be any worse, AFAICT.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread William E. Kempf

Fernando Cacciola said:
>> As did I in the interface I proposed elsewhere.  My complaint wasn't
>> actually the lack of an operator=(), but of the lack of any way to
>> reassign the value in an efficient and uniform manner.
>>
> But what's wrong with: *opt = new_value?
> This is as efficient and as uniform as anything else.
>
> btw: your next response arrived so I can see that you think that *opt=x
> only works if opt is initialized...
> But it isn't the case!
> *opt=x actually initializes the optional if it not initialized. And this
> is why the proxy is needed...

Then your documentation is wrong!  To quote:

"proxy optional::operator* () ;

   If the optional object is initialized, returns a proxy object which
allows mutable access to its value (of type T).

   If it is uninitialized, the result is undefined (but BOOST_ASSERT is
used so the user can define this behavior in a debug build)."

I can not assign to an uninitialized optional through operator*() because
that results in undefined behavior.  Now I assume that this was the reason
for the proxy... so you could assign to an uninitialized optional.  But I
think that's a bad idea, because the assignment would be the only valid
thing you could do here, which is just plain confusing.  But even if I
thought we should keep the concept of the proxy, your documentation is
simply incorrect.

> But then of course you will say:
> why don't you have *opt=x work *only* for initialized optionals, and use
> reset() to initialize it.

Yes!

> OK. This could work... I'll think about it further.
>
>> But that's not the case here.  The current interface provides no way
>> to _efficiently_ change the value.  (That is, with out regard for
>> whether or not the optional has been initialized.)
>>
> Actually, it does.
> *opt = new_value.
> changes the value even if it isn't initialized.
> But since you didn't expected such a behaviour it turns out that it
> might be confusing.

I didn't expect the behavior mostly because the documentation clearly says
this isn't legal.  However, it would be surprising to include the single
use case of assignment to an uninitialized optional, yes.

> Clearly, if *opt=x only works for initialized optionals, reset() is
> needed.
>
> So we need to discuss this:  should *opt=x assign even uninitialized
> optionals? (as it does now)
> Or should reset() do that?

My vote is for reset(), as it provides the cleanest interface.

>> > I know that since you construct an optional with a value, and since
>> you can turn an optional into the uninitialized state, it is
>> actually 'similar' to a container, but there is a difference: when
>> you construct an optional<> with a value, the optional uses the
>> value to initialize its own value, it is not 'takinging it' (it
>> isn't containing it). Similarly, when you 'uninitialize' an
>> optional, it is destroying its value, but it is not taking it out
>> (otherwise uninitialize would return the previosu value).
>>
>> I think you're trying to convey too much with the naming, with the
>> result being that the interface is actually _less_ understandable.
>>
> Notice that a smart pointer has a reset, but it takes a new pointer, not
> a new object value.

So what?  Containers store values.  So do smart pointers, even though the
value stored is a pointer.

> If optional<> had a resest, it would be *similar* to that of a smart
> pointer,
> but just similar because it would not take a pointer.

Which bothers me less than using an interface that's mostly likely a smart
pointer except in these unecessary details (the detail that it doesn't
take a pointer is necessary, but the others are clearly not).

> It would have to be assymetric with get(), for example.
> This is why I said that extending the analogy to a smart pointer too
> much might lead to confusion.

I think it leads to a more understandable interface... but we'll have to
let others voice their opinions as well.

>> I don't agree with that rationale.  If it walks like a duck, and
>> quacks like a duck...
>>
> But does it walk and quack like a duck? or just looks like? :-))
> We need to figure this out, and we could use some external input for
> this...

It provides operator*(), and operator->(), so it walks like a duck and
talks like a duck.

>> > Now I want peek() even more than before, precisely to stress out
>> that is not containing
>> > a poiner.
>>
>> I don't think that peek() conveys that information.  But let's assume
>> it does.  Doesn't the name and purpose of optional<> already convey
>> that?
>>
> That?
> Do you understad what that the name peek() is intended to convey?

I believe so, and I believe that the name optional conveys it already.

> I will drop it if people want it that way, but I'd like it to be
> understood what peek() is about.
> It has nothing to do with optional<>, really, is about drawing a
> distinction between 'peeking' inside an object as opposed to
> 'extracting' from it (with a complete transfer or distribution of
> owners

Re: [boost] Formal review: Optional library

2002-12-11 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > > Currently, you can change the value of the optional directly without
any
> > > performance
> > > penalty like this: *opt = new_val, so I don't see any real need for
> > reset().
> >
> > Not correct, *opt has undefined behavior when opt is uninitialized.
> >
> Funny...
> The truth is that *opt has defined behaviour even if it is uninitialized
> when
> used as an lvalue: it can be reset to initialized.
> IOWs, *opt=x is exactly like opt.reset(x).
>
> This is clearly documented, clearly shown on the examples,
> but apparently, clearly wrong :-)
> (otherwise, you and William wouldn't have mistaken it)

The documentation for

proxy optional::operator* ();

says that the behavior is undefined when *this is uninitialized.

The example for proxy::operator= assigns to an initialized optional:

T v0 ;
optional opt(v0);
T v1 ;
*opt = v1;
assert ( *opt == v1 ) ;

If the documentation is wrong (or am I looking at the wrong version?) and
the intent of the proxy is to allow *opt = v, having '*opt' be legal for
non-const opt but illegal for a const opt probably isn't a good idea.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 10:21 AM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > I still don't like to think of optional<> as a container, so I still
don't
> > like this reset.
>
> I don't see why. reset() has nothing to do with containership; it's a
> generic shorthand for reconstructing an object in place.
>
> void X::reset(args)
>
> Effects: destroys the contents of *this (if any)
> Postconditions: *this is equivalent to X(args)
>
OK.

>
> > Currently, you can change the value of the optional directly without any
> > performance
> > penalty like this: *opt = new_val, so I don't see any real need for
> reset().
>
> Not correct, *opt has undefined behavior when opt is uninitialized.
>
Funny...
The truth is that *opt has defined behaviour even if it is uninitialized
when
used as an lvalue: it can be reset to initialized.
IOWs, *opt=x is exactly like opt.reset(x).

This is clearly documented, clearly shown on the examples,
but apparently, clearly wrong :-)
(otherwise, you and William wouldn't have mistaken it)

I'll post a sub-thread to discuss this (mis?)feature on its own.
It has important derivations, such as the need for the proxy and
hence .value().

I think that if this behaviour is removed, the interface proposed by William
might work fine.

Fernando Cacciola



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "David Abrahams" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Wednesday, December 11, 2002 11:14 AM
Subject: Re: [boost] Formal review: Optional library


> "Fernando Cacciola" <[EMAIL PROTECTED]> writes:
>
> > Currently, the non-POD case implementation goes like this:
> >
> > (this is a sketch actually)
> >
> > template
> > class optional1
> > {
> >   optional1 ( T const& v ) { p = new (buffer.address()) T(v) ; }
> >
> >   T const& operator *() { return *p; } // Dereference here
> >
> >   aligned_storage buffer ;
> >   T* p ;
> > }  ;
>
> There's no need to store p. You can just use
> static_cast(buffer.address())
>
Yes.. I just shown the pointer explicitely.
The result of the static_cast<> is a pointer, so to obtain a reference (for
the operator*) you need to 'actually' dereference this poiner.

> > OTOH, when T is a POD, so there is no need to bypass its ctor
> > (since it has a trivial ctor),
> > the implementation goes like this:
> >
> > template
> > class optional2
> > {
> >   optional2 ( T const& val ) v(val) {}
> >
> >   T const& operator *() { return val; } // No Dereference here
> >
> >   T val ;
> > } ;
> >
> > Anyway, if yoy know how to make an efficient implementation like
> > the second one with an aligned storage I'll be happy to use it.
>
> Why do you think that will be any more efficient than the other
> implementation when T is POD?
>
For POD types: operator*() "directly" returns the value.
The key is that for POD types, since optional wraps just T (unlike any
variant) and nothing else, aligned_storage is not required.
optional<> simply contains a data member of type T, that's all.

If you still don't see it I can show you the typical machine generated code
for both implementations for operator*().

Fernando Cacciola


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola
- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 7:04 PM
Subject: Re: [boost] Formal review: Optional library

>
> Fernando Cacciola said:
>
> > But if I wrote:
> >
> > optional x = foo();
> > if ( x )
> >   some(x);
> >
> > it really looked as if it were testing if 'x' is initialized
> > while it was acutally comparing the 'x' value against 0.
>
> I'm not sure I find this compelling.  Knowing that a test for
> initialization is done through optional::initialized(), I'd never mistake
> the if above for testing this.  This would cause problems only with
> someone unfamiliar with optional, but they are going to have problems no
> matter what interface you choose until they read the documentation.
>
... but I would make such mistakes, and I know too many people that would
also do it.

> > Eventually, I realized that value semantics are not really appropiate to
> > deal
> > with unininitialized states since it blurs the distinction between
> > testing against other values and testing whether it is initialized or
> > not. So I wonder which other semantics would deal with it properly,
> > and pointers poped into my mind quickly.
>
> But pointers are just the inverse of the problem above.  Test for validity
> is bald.

Only if safe_bool isn't used.
But, I'm just about to be convinced to added it, in which case,
test for validity will look just like it looks like
for any other smart/bare pointer.

>, while access to the "value" requires some supporting syntax (in
> this case, operator*).  This leaves users in the exact same scenario where
> a simple mistake leads to code that compiles but doesn't do what the
> programmer meant.

Can you give me an example of something that compiles but
doesn't do what the programmer meant?
Remeber that currently *opt=x is defined even if opt is uninitialized

> I think you're trying just a little too hard to make
> the interface "idiot proof".
>
Fair enough. I tend to do this, I know.
Maybe is becasue I use to work late at night, so I better protect myself
from myself :-))

> >> Now, assuming we stick with pointer semantics, let's make this as
> >> close to the "normal" smart pointer interface as possible:
> >>
> >> template 
> >> class optional
> >> {
> >> public:
> >>optional();
> >>explicit optional(T const& value);
> >>optional(optional const& other);
> >>template 
> >>   optional(optional const& other);
> >>~optional();
> >>
> >>T& operator*() const;
> >>T* operator->() const;
> >>T* get() const;
> >>// T* release();
> >>void reset();
> >>void reset(T const& value);
> >>operator unspecified-bool-type() const;
> >> };
> >>
> >>
> > This interface is greatly simplified mainly because
> > my interface offers deep-constantness:
> >
> > T const* peek() const ;
> > T*   peek();
> > T const& operator*() const;
> > prxy operator*() ;
> >
> > instead of:
> >
> > T* peek() const ;
> > T& operator*() const;
> >
> > The proxy is needed *only* to achieve deep-constantness.
> > If this feature weren't introduced, my interface would have looked just
> > like yours.
>
> I still don't see the need for the proxy.  The interface I gave could
> provide "deep-constantness" with out a proxy.  I'm not sure where I stand
> on whether or not optional<> should provide this, however.
>
Right. I mistakenly forgot what the proxy is for...
it has nothing to do with deep-constantness... o-)
it is required to support *opt=x for uninitialized optionals, which reset
'opt'
to initilized.

But wait
I will have to discuss this feature (?) on its own, so I'll top post this
issue.

> >> Semantics and rationale:
> >>
> >> optional()
> >>
> >>Constructs an "uninitialized" optional.
> >>
> >> explicit optional(T const& value)
> >>
> >>Constructs an optional initialized to value through copy
> >> construction.
> >>
> >> optional(optional const& other)
> >>
> >>Copy constructs an optional using the value-type's copy
> >> constructor.
> >>
> >> template  optional(optional const& other)
> >>
> >>Allows copy constr

Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola
- Original Message -
From: "Tanton Gibbs" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 10:10 PM
Subject: Re: [boost] Formal review: Optional library


> > > > That's why it hands you a pointer to the value, because you can test
> the
> > > > pointer
> > > > for NULL; but that's it.
> > > > IOWs, the pointer returned by optional is conceptually a handle, not
a
> > > > pointer.
> > > > That's why I like the member function peek() much better than get().
> > >
> > > I still much prefer the standard get(), even if I bought into the rest
> of
> > > the rationale.  It's what people expect because of std::auto_ptr.
> > >
> > I see.
> > I counted 2(two) in favor of get(), and one (me :-) in favor of peek().
> > I'll be democratic on this one, though I hope I can get more counts.
>
> For what its worth, I vote in favor of value semantics.  It seems much
> easier
> to me to remember to call initialized when I want to test validity than it
> does
> to remember which of *, peek, get, get_value to use in which case.  Also,
> the fact that I can assign a non pointer value to a smart-pointer is kinda
> strange.
> To me, it just doesn't fit the smart pointer mold and the interface is
> confusing
> because it is trying to shape an elephant into a rhino -- yeah, their
close,
> but
> shaping a hippo to a rhino might be easier.  Therefore, I urge you to
> reconsider
> value semantics as I think those examples were much cleaner and clearer
than
> the examples I have been seeing.
>
> Thanks,
> Tanton
>
value semantics were not just considered but used.
The original optional<> I implemented used value semantics,
but after a long time, I found it a lot more confusing that
with value semantics.
Pointers convey the notion of uninitialization quite naturally.
For instance, for an optional argument to a function
pointer are typically used.
Consider:

void foo ( int* opt )
{
  if ( opt )
  {
bar(*opt);
  }
}
foo(NULL);

this is the typical way you deal with an optional argument.
optional<> follows the same pattern for those cases were true
pointers cannot be used since it would require a dynamic
allocation.

optional foo()
{
  return optional(3);
}
void gee()
{
  optional opt = foo();
  if ( opt )  // pretend safe-bool is added
bar(*opt);
}

There is an analogy between the way pointers are ordinarily used
for optional function arguments and optional<>. The analogy
should help users become familiar with optional<>.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "David Abrahams" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 10:00 PM
Subject: Re: [boost] Formal review: Optional library


> "Fernando Cacciola" <[EMAIL PROTECTED]> writes:
>
>
> > I still don't like to think of optional<> as a container, so I still
> > don't like this reset.
>
> Do you really think of auto_ptr and shared_ptr as containers? They
> seem to have little or nothing in common with any of the standard
> containers.
>
OK.
After further thinking I agree that optional<> is as much as a container
as a smart pointer -not much really-, meaning that you pass a value which
is contained within the wrapper and which you can access it.

> > My motivation against this is just to prevent potential problems with
> > optional, but if we collectively conclude that those problems
> > are not so much important, I will add the safe_bool and
> > make sure to tell every not to use optional (and use tribool
instead)
> > or else to use it with caution.
>
> I don't think any special warnings are needed; the problem case you
> cite seems contrived to me.
>
Perhaps.
Anyway, if I add safe_bool (and it looks like I will) I will explain
the potential problems in the docs just in case.

> > I'm not sure what would be effect of removing deep-constantness.
> > It would definitely allow the leaner interface you are proposing,
>
> Well, deep-constantness is utterly inconsistent with the pointer-like
> semantics you claim to be implementing.  A pointer-ish optional
> component is a fine idea, but why not follow through all the way with
> the idiom?
>
How is deep-constantness utterly incosistent with pointer-like semantics?

> > This is a possibility.
> > I could accept something like this, though I constantly see
> > people complaining about lack of deep constantness on wrappers like
> > optional<>
> > What do others think?
>
> Is it a wrapper or a pointer?
>
Is a wrapper which acts partially like a pointer.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread David Abrahams
"Fernando Cacciola" <[EMAIL PROTECTED]> writes:

> Currently, the non-POD case implementation goes like this:
>
> (this is a sketch actually)
>
> template
> class optional1
> {
>   optional1 ( T const& v ) { p = new (buffer.address()) T(v) ; }
>
>   T const& operator *() { return *p; } // Dereference here
>
>   aligned_storage buffer ;
>   T* p ;
> }  ;

There's no need to store p. You can just use
static_cast(buffer.address())

> OTOH, when T is a POD, so there is no need to bypass its ctor
> (since it has a trivial ctor),
> the implementation goes like this:
>
> template
> class optional2
> {
>   optional2 ( T const& val ) v(val) {}
>
>   T const& operator *() { return val; } // No Dereference here
>
>   T val ;
> } ;
>
> Anyway, if yoy know how to make an efficient implementation like
> the second one with an aligned storage I'll be happy to use it.

Why do you think that will be any more efficient than the other
implementation when T is POD?

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "David Abrahams" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 9:53 PM
Subject: Re: [boost] Formal review: Optional library


> [SNIP]
>
> "Joel de Guzman" <[EMAIL PROTECTED]> writes:
>
> >> Not so...
> >> The low-level implementation is like a variant ONLY is the wrapped
object is
> >> not a POD.
> >> When you have, say, optional, the implementation uses: struct {
int
> >> m_value ; bool m_initialized }
> >> As a result, value access, via operator*() is more efficient since it
> >> doesn't dereference a pointer.
> >
> > That depends on how the variant is implemented. Which variant
> > implementation are you referring to? I'm sorry. I'm confused with
> > what you are saying. I can't see why it is more efficient. Neither do
> > I see a dereference in any case.
>
> I'm with Joel on this one. It seems to me that no special optimization
> should be needed for PODs; all you should need is some aligned storage
> in which to construct the contained object and one or more bits to
> indicate which of the allowed types (if any) is held there.
>
Let's see:

Currently, the non-POD case implementation goes like this:

(this is a sketch actually)

template
class optional1
{
  optional1 ( T const& v ) { p = new (buffer.address()) T(v) ; }

  T const& operator *() { return *p; } // Dereference here

  aligned_storage buffer ;
  T* p ;
}  ;

The object is effectively contained in an aligned storage.
AFAIK, to access the object I need to address the storage, for which
I need a pointer. But then, in order to return a reference to
the object, I need to dereference the pointer.

OTOH, when T is a POD, so there is no need to bypass its ctor
(since it has a trivial ctor),
the implementation goes like this:

template
class optional2
{
  optional2 ( T const& val ) v(val) {}

  T const& operator *() { return val; } // No Dereference here

  T val ;
} ;

Anyway, if yoy know how to make an efficient implementation like
the second one with an aligned storage I'll be happy to use it.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
> value() is there just because the proxy() fails to convert to T&;
> and the proxy is needed by the deep-constantess,

What is wrong with

T & operator*();
T const & operator*() const;

?

> Of course, it can be argued that if you wanted
> to convey true constantness you should write:
>
> void foo ( optional const& opt )
>
> instead.
>
> This is a possibility.
> I could accept something like this, though I constantly see
> people complaining about lack of deep constantness on wrappers like
> optional<>
> What do others think?

Others think that, in spite of your insistence that optional is not a
container, it is a container (size 0-1, fixed capacity of 1, typical
container semantics of keeping extra capacity uninitialized), and deep
constness is entirely appropriate. ;-)

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Fernando Cacciola

- Original Message -
From: "Joel de Guzman" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 8:53 PM
Subject: Re: [boost] Formal review: Optional library


>
> - Original Message -
> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
> > > Hmmm, I'm not sure if I agree with this. T can very well be
> > > uninitialized in the variant when nil_t is in effect. Then
> > > nil_t can just be struct nil_t {}; which costs nothing to initialize.
> > > Why is optional "more handy" in this regard?
> > >
> > Because it has an interface that makes it easier to deal with its
possibly
> > uninitialized state:
> >
> > optional opt ;
> > int x = *opt ; // Oops! opt is uninitialied. In debug this is an
assertion
> > failure, in release, a core-dump.
> >
> > *opt = 3 ; // initializes it.
> >
> > if ( int* x = get(opt) )
> >   some(*x)
>
> But of course you also have that interface with the variant.
> Example:
>
>  if (p = variant_cast(pvar))
>  ...initialized
>  else
> ...uninitialized
>
> or...
>
>   int n = variant_cast(var);
>   // Oops! var is uninitialied. throws bad_cast
>
> It's trivial to make that a free function like get. Or further, to make
> a subset API for optional.
>
You can certainly do the same with variant. The point is that with
optional<> it is *easier*.
With optional<> you don't need to specify the type of the wrapped value all
the time as with variant; and you don't need to explicitly test if the
variant holds a "nil_t" in order to see if it is initialized.

Fernando Cacciola


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> I still don't like to think of optional<> as a container, so I still don't
> like this reset.

I don't see why. reset() has nothing to do with containership; it's a
generic shorthand for reconstructing an object in place.

void X::reset(args)

Effects: destroys the contents of *this (if any)
Postconditions: *this is equivalent to X(args)

> Currently, you can change the value of the optional directly without any
> performance
> penalty like this: *opt = new_val, so I don't see any real need for
reset().

Not correct, *opt has undefined behavior when opt is uninitialized.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-11 Thread Peter Dimov
From: "Joel de Guzman" <[EMAIL PROTECTED]>
> 
> Or perhaps, optional is just a limited add-on API over the variant?

Or perhaps optional is just a limited API over a container?
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Tanton Gibbs
> > > That's why it hands you a pointer to the value, because you can test
the
> > > pointer
> > > for NULL; but that's it.
> > > IOWs, the pointer returned by optional is conceptually a handle, not a
> > > pointer.
> > > That's why I like the member function peek() much better than get().
> >
> > I still much prefer the standard get(), even if I bought into the rest
of
> > the rationale.  It's what people expect because of std::auto_ptr.
> >
> I see.
> I counted 2(two) in favor of get(), and one (me :-) in favor of peek().
> I'll be democratic on this one, though I hope I can get more counts.

For what its worth, I vote in favor of value semantics.  It seems much
easier
to me to remember to call initialized when I want to test validity than it
does
to remember which of *, peek, get, get_value to use in which case.  Also,
the fact that I can assign a non pointer value to a smart-pointer is kinda
strange.
To me, it just doesn't fit the smart pointer mold and the interface is
confusing
because it is trying to shape an elephant into a rhino -- yeah, their close,
but
shaping a hippo to a rhino might be easier.  Therefore, I urge you to
reconsider
value semantics as I think those examples were much cleaner and clearer than
the examples I have been seeing.

Thanks,
Tanton

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread David Abrahams
"Fernando Cacciola" <[EMAIL PROTECTED]> writes:


> I still don't like to think of optional<> as a container, so I still
> don't like this reset.

Do you really think of auto_ptr and shared_ptr as containers? They
seem to have little or nothing in common with any of the standard
containers.

> My motivation against this is just to prevent potential problems with
> optional, but if we collectively conclude that those problems
> are not so much important, I will add the safe_bool and
> make sure to tell every not to use optional (and use tribool instead)
> or else to use it with caution.

I don't think any special warnings are needed; the problem case you
cite seems contrived to me.

> I'm not sure what would be effect of removing deep-constantness.
> It would definitely allow the leaner interface you are proposing,

Well, deep-constantness is utterly inconsistent with the pointer-like
semantics you claim to be implementing.  A pointer-ish optional
component is a fine idea, but why not follow through all the way with
the idiom?

> This is a possibility.
> I could accept something like this, though I constantly see
> people complaining about lack of deep constantness on wrappers like
> optional<>
> What do others think?

Is it a wrapper or a pointer?

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread David Abrahams
"Joel de Guzman" <[EMAIL PROTECTED]> writes:

> - Original Message - 
> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
>> > > optional captures the zero/one distinction, which, as its analogy to
>> > > pointers makes clear, is a very useful one.  A type which can contain
>> > > any number of different types would have a much more complicated
>> > > interface.  Maybe it's just a different library?
>> >
>> > Or perhaps, optional is just a limited add-on API over the variant?
>> > The low-level  implementation mechanism in place seems to be very
>> > similar and having 2 separate libraries will be redundant, I think.
>> >
>> Not so...
>> The low-level implementation is like a variant ONLY is the wrapped object is
>> not a POD.
>> When you have, say, optional, the implementation uses: struct { int
>> m_value ; bool m_initialized }
>> As a result, value access, via operator*() is more efficient since it
>> doesn't dereference a pointer.
>
> That depends on how the variant is implemented. Which variant
> implementation are you referring to? I'm sorry. I'm confused with
> what you are saying. I can't see why it is more efficient. Neither do
> I see a dereference in any case.

I'm with Joel on this one. It seems to me that no special optimization
should be needed for PODs; all you should need is some aligned storage
in which to construct the contained object and one or more bits to
indicate which of the allowed types (if any) is held there.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Joel de Guzman

- Original Message - 
From: "Fernando Cacciola" <[EMAIL PROTECTED]>

> > Hmmm, I'm not sure if I agree with this. T can very well be
> > uninitialized in the variant when nil_t is in effect. Then
> > nil_t can just be struct nil_t {}; which costs nothing to initialize.
> > Why is optional "more handy" in this regard?
> >
> Because it has an interface that makes it easier to deal with its possibly
> uninitialized state:
> 
> optional opt ;
> int x = *opt ; // Oops! opt is uninitialied. In debug this is an assertion
> failure, in release, a core-dump.
> 
> *opt = 3 ; // initializes it.
> 
> if ( int* x = get(opt) )
>   some(*x)

But of course you also have that interface with the variant.
Example:

 if (p = variant_cast(pvar))
 ...initialized
 else
...uninitialized

or...

  int n = variant_cast(var);
  // Oops! var is uninitialied. throws bad_cast

It's trivial to make that a free function like get. Or further, to make
a subset API for optional.

Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com




___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "Joel de Guzman" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 6:47 PM
Subject: Re: [boost] Formal review: Optional library


>
> - Original Message -
> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
> > - Original Message -
> > From: "Joel de Guzman" <[EMAIL PROTECTED]>
>
> > > Hi,
> > >
> > > Probably a dumb question but allow me to ask anyway:
> > >
> > > Wouldn't a more generic variant class do what the
> > > optional is trying to do? I feel that optional is just a variant > nil_t>
> > > in disguise. Correct me if I'm wrong.
> > >
> > The difference is that optional<> *explicitly* deals with the
possibility of
> > being
> > uninitialized, while variant doesn't. (for the later, nil_t is
just
> > another possible value).
> >
> > In this regard optional<> is more handy for its intended usage.
>
> Hmmm, I'm not sure if I agree with this. T can very well be
> uninitialized in the variant when nil_t is in effect. Then
> nil_t can just be struct nil_t {}; which costs nothing to initialize.
> Why is optional "more handy" in this regard?
>
Because it has an interface that makes it easier to deal with its possibly
uninitialized state:

optional opt ;
int x = *opt ; // Oops! opt is uninitialied. In debug this is an assertion
failure, in release, a core-dump.

*opt = 3 ; // initializes it.

if ( int* x = get(opt) )
  some(*x)

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 4:18 PM
Subject: Re: [boost] Formal review: Optional library

> [snipped]
>
> But I do see reasons to want to keep with a smart pointer design and am
> not (necessarily) trying to convince you to switch to value semantics.
>
Good.

> All I'm saying is that if we retain a smart pointer design, we should be
> faithful to that decision.
>
Fair enough.
In another post, I'll summarize the 'distance' between the current
'smart-pointer-likeness' and a full smart-pointer-like interface
so we can focus on it specifically.
I need the opinion of other reviewers.

>
> > That's why it hands you a pointer to the value, because you can test the
> > pointer
> > for NULL; but that's it.
> > IOWs, the pointer returned by optional is conceptually a handle, not a
> > pointer.
> > That's why I like the member function peek() much better than get().
>
> I still much prefer the standard get(), even if I bought into the rest of
> the rationale.  It's what people expect because of std::auto_ptr.
>
I see.
I counted 2(two) in favor of get(), and one (me :-) in favor of peek().
I'll be democratic on this one, though I hope I can get more counts.

>
> >> As long as there's a
> >> constructor taking a value, it seems logical to me there should be an
> >> assignment taking a value.
> >
> > There is an asymmetry here, certainly.
> > Originally, optional<> did not have a constructor taking a value,
> > precisely in order to keep it symmetry, but it was argued that it
> > cluttered the interface too much, so I eventually bent my mind and added
> > the constructor.
>
> As did I in the interface I proposed elsewhere.  My complaint wasn't
> actually the lack of an operator=(), but of the lack of any way to
> reassign the value in an efficient and uniform manner.
>
But what's wrong with: *opt = new_value?
This is as efficient and as uniform as anything else.

btw: your next response arrived so I can see that you think that *opt=x only
works if opt is initialized...
But it isn't the case!
*opt=x actually initializes the optional if it not initialized. And this is
why the proxy is needed...

But then of course you will say:
why don't you have *opt=x work *only* for initialized optionals, and use
reset() to initialize it.

OK. This could work... I'll think about it further.

> But that's not the case here.  The current interface provides no way to
> _efficiently_ change the value.  (That is, with out regard for whether or
> not the optional has been initialized.)
>
Actually, it does.
*opt = new_value.
changes the value even if it isn't initialized.
But since you didn't expected such a behaviour it turns out that it might be
confusing.

Clearly, if *opt=x only works for initialized optionals, reset() is needed.

So we need to discuss this:  should *opt=x assign even uninitialized
optionals? (as it does now)
Or should reset() do that?

>
> > I know that since you construct an optional with a value, and since you
> > can turn an optional into the uninitialized state, it is actually
> > 'similar' to a container, but there is a difference: when you construct
> > an optional<> with a value, the optional uses the value to initialize
> > its own value, it is not 'takinging it' (it isn't containing it).
> > Similarly, when you 'uninitialize' an optional, it is destroying its
> > value, but it is not taking it out (otherwise uninitialize would return
> > the previosu value).
>
> I think you're trying to convey too much with the naming, with the result
> being that the interface is actually _less_ understandable.
>
Notice that a smart pointer has a reset, but it takes a new pointer, not a
new object value.
If optional<> had a resest, it would be *similar* to that of a smart
pointer,
but just similar because it would not take a pointer.
It would have to be assymetric with get(), for example.
This is why I said that extending the analogy to a smart pointer too much
might lead to confusion.

> >> > If I manage to make the idiom known enough, the user will know that
> >> he can't delete the pointer and that the pointer can be used only as
> >> long as the 'source' (the optional<> object in this case) remains
> >> alive.
> >>
> >> OK, that rationale makes some sense, though I don't think it's that
> >> necessary to deviate the names here to indicate the unusual ownership
> >> semantics.  I think the class name and purpose 

Re: [boost] Formal review: Optional library

2002-12-10 Thread Joel de Guzman

- Original Message - 
From: "Fernando Cacciola" <[EMAIL PROTECTED]>

> > > optional captures the zero/one distinction, which, as its analogy to
> > > pointers makes clear, is a very useful one.  A type which can contain
> > > any number of different types would have a much more complicated
> > > interface.  Maybe it's just a different library?
> >
> > Or perhaps, optional is just a limited add-on API over the variant?
> > The low-level  implementation mechanism in place seems to be very
> > similar and having 2 separate libraries will be redundant, I think.
> >
> Not so...
> The low-level implementation is like a variant ONLY is the wrapped object is
> not a POD.
> When you have, say, optional, the implementation uses: struct { int
> m_value ; bool m_initialized }
> As a result, value access, via operator*() is more efficient since it
> doesn't dereference a pointer.

That depends on how the variant is implemented. Which variant
implementation are you referring to? I'm sorry. I'm confused with
what you are saying. I can't see why it is more efficient. Neither do
I see a dereference in any case.

Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "Joel de Guzman" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 7:04 PM
Subject: Re: [boost] Formal review: Optional library


>
> - Original Message -
> From: "David Abrahams" <[EMAIL PROTECTED]>
>
>
> > "Joel de Guzman" <[EMAIL PROTECTED]> writes:
> >
> > > - Original Message -
> > > From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > >
> > >
> > >
> > >> optional<> is trying to model using C++ a concept that
> > >> it is not really covered by the language, that of uninitialzed
values.
> > >> It uses pointer semantics *just* because pointers are the only sort
of
> > >> C++ objects which has a clear uninitialized state.
> > >
> > > Hi,
> > >
> > > Probably a dumb question but allow me to ask anyway:
> > >
> > > Wouldn't a more generic variant class do what the
> > > optional is trying to do? I feel that optional is just a variant
> > > in disguise. Correct me if I'm wrong.
> >
> > Someone once said that if a theorem in Physics involves numbers other
> > than zero, 1, or infinity, it's lacking in purity.
>
> :-) Cool!
>
> > optional captures the zero/one distinction, which, as its analogy to
> > pointers makes clear, is a very useful one.  A type which can contain
> > any number of different types would have a much more complicated
> > interface.  Maybe it's just a different library?
>
> Or perhaps, optional is just a limited add-on API over the variant?
> The low-level  implementation mechanism in place seems to be very
> similar and having 2 separate libraries will be redundant, I think.
>
Not so...
The low-level implementation is like a variant ONLY is the wrapped object is
not a POD.
When you have, say, optional, the implementation uses: struct { int
m_value ; bool m_initialized }
As a result, value access, via operator*() is more efficient since it
doesn't dereference a pointer.

Fernando Cacciola


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Joel de Guzman

- Original Message - 
From: "Joel de Guzman" <[EMAIL PROTECTED]>


> - Original Message - 
> From: "David Abrahams" <[EMAIL PROTECTED]>

> > optional captures the zero/one distinction, which, as its analogy to
> > pointers makes clear, is a very useful one.  A type which can contain
> > any number of different types would have a much more complicated
> > interface.  Maybe it's just a different library?
> 
> Or perhaps, optional is just a limited add-on API over the variant?
> The low-level  implementation mechanism in place seems to be very
> similar and having 2 separate libraries will be redundant, I think.

But then of course, we don't have a variant yet. Duh! So, 
please take my opinions as just food for thought. Maybe sometime
in the future the optional and the variant may be factored out
to share some common code. Nothing wrong with forward thinking
eh? 

As it is, I'll have plenty of uses for the optional. I vote to accept.

Cheers,
Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Joel de Guzman

- Original Message - 
From: "David Abrahams" <[EMAIL PROTECTED]>


> "Joel de Guzman" <[EMAIL PROTECTED]> writes:
> 
> > - Original Message - 
> > From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> >
> >
> >
> >> optional<> is trying to model using C++ a concept that
> >> it is not really covered by the language, that of uninitialzed values.
> >> It uses pointer semantics *just* because pointers are the only sort of
> >> C++ objects which has a clear uninitialized state.
> >
> > Hi,
> >
> > Probably a dumb question but allow me to ask anyway:
> >
> > Wouldn't a more generic variant class do what the 
> > optional is trying to do? I feel that optional is just a variant
> > in disguise. Correct me if I'm wrong.
> 
> Someone once said that if a theorem in Physics involves numbers other
> than zero, 1, or infinity, it's lacking in purity.

:-) Cool! 
 
> optional captures the zero/one distinction, which, as its analogy to
> pointers makes clear, is a very useful one.  A type which can contain
> any number of different types would have a much more complicated
> interface.  Maybe it's just a different library?

Or perhaps, optional is just a limited add-on API over the variant?
The low-level  implementation mechanism in place seems to be very
similar and having 2 separate libraries will be redundant, I think.

Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com




___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread William E. Kempf

Fernando Cacciola said:
> From: "William E. Kempf" <[EMAIL PROTECTED]>
>> OK, I've been thinking about the interface a bit more and want to
>> voice some other opinions.  First, why were pointer semantics chosen
>> at all? Why couldn't you have gone with value semantics?
>>
>> optional foo()
>> {
>>//...
>> }
>>
>> void bar(int value)
>> {
>>//...
>> }
>>
>> optional res = foo();
>> if (res.initialized())
>>bar(res);
>>
>> I can think of a few reasons, but want to hear about them from the
>> designer, and want to see the rationale documented.
>>
> Fair enough.
> Originally, optional<> had value semantics, so I used it pretty much
> like in the examples you've shown.
> But I had problem: since it had value semantics, it was perfectly OK to
> write:
>
> optional x = foo();
> if ( x == 0 )
>   some();
>
> Or even:  if ( x ) some(x);
>
> Meaning "compare the 'value' of x against 0".
>
> Therefore, I needed something explicitely different to test
> if it was initialized or not:
>
> optional x = foo();
> if ( x.initialied() )
>   some(x);

Which is what I illustrated above ;).

> But if I wrote:
>
> optional x = foo();
> if ( x )
>   some(x);
>
> it really looked as if it were testing if 'x' is initialized
> while it was acutally comparing the 'x' value against 0.

I'm not sure I find this compelling.  Knowing that a test for
initialization is done through optional::initialized(), I'd never mistake
the if above for testing this.  This would cause problems only with
someone unfamiliar with optional, but they are going to have problems no
matter what interface you choose until they read the documentation.

> Eventually, I realized that value semantics are not really appropiate to
> deal
> with unininitialized states since it blurs the distinction between
> testing against other values and testing whether it is initialized or
> not. So I wonder which other semantics would deal with it properly,
> and pointers poped into my mind quickly.

But pointers are just the inverse of the problem above.  Test for validity
is bald, while access to the "value" requires some supporting syntax (in
this case, operator*).  This leaves users in the exact same scenario where
a simple mistake leads to code that compiles but doesn't do what the
programmer meant.  I think you're trying just a little too hard to make
the interface "idiot proof".

>> Now, assuming we stick with pointer semantics, let's make this as
>> close to the "normal" smart pointer interface as possible:
>>
>> template 
>> class optional
>> {
>> public:
>>optional();
>>explicit optional(T const& value);
>>optional(optional const& other);
>>template 
>>   optional(optional const& other);
>>~optional();
>>
>>T& operator*() const;
>>T* operator->() const;
>>T* get() const;
>>// T* release();
>>void reset();
>>void reset(T const& value);
>>operator unspecified-bool-type() const;
>> };
>>
>>
> This interface is greatly simplified mainly because
> my interface offers deep-constantness:
>
> T const* peek() const ;
> T*   peek();
> T const& operator*() const;
> prxy operator*() ;
>
> instead of:
>
> T* peek() const ;
> T& operator*() const;
>
> The proxy is needed *only* to achieve deep-constantness.
> If this feature weren't introduced, my interface would have looked just
> like yours.

I still don't see the need for the proxy.  The interface I gave could
provide "deep-constantness" with out a proxy.  I'm not sure where I stand
on whether or not optional<> should provide this, however.

>> Semantics and rationale:
>>
>> optional()
>>
>>Constructs an "uninitialized" optional.
>>
>> explicit optional(T const& value)
>>
>>Constructs an optional initialized to value through copy
>> construction.
>>
>> optional(optional const& other)
>>
>>Copy constructs an optional using the value-type's copy
>> constructor.
>>
>> template  optional(optional const& other)
>>
>>Allows copy construction from "compatible" optionals (optionals
>> with
>> value types that can be used for constructing this optional's value
>> type).  I'm not sure how important this one is for optional, to be
>> honest.
>>
> I've never needed to convert between optinals.
> On a related note, if deep-constantess is not supported
> (as in your interface), an implicit conversion from
> optional to optional is needed because
> the user will have to use  to attach constantess
> to the value.

Actually, it's still not needed.

optional opt1(666);
optional opt2(*opt1);

Granted, it *IS* an important convenience, since you don't have to check
the initialized state, but it's not strictly necessary.

>> ~optional()
>>
>>If the optional is initialized, calls the value-type's destructor.
>>
>
> Why isn't assignment supplied?

Because I believe the reset is clearer, and safer.

>> T& operator*() const
>>
>>If the optional is not initialized, results in undefined behavior.
>> Otherwise, returns a reference to the value.
>>
>> T* operator->(

Re: [boost] Formal review: Optional library

2002-12-10 Thread Joel de Guzman

- Original Message - 
From: "Fernando Cacciola" <[EMAIL PROTECTED]>

> - Original Message -
> From: "Joel de Guzman" <[EMAIL PROTECTED]>

> > Hi,
> >
> > Probably a dumb question but allow me to ask anyway:
> >
> > Wouldn't a more generic variant class do what the
> > optional is trying to do? I feel that optional is just a variant nil_t>
> > in disguise. Correct me if I'm wrong.
> >
> The difference is that optional<> *explicitly* deals with the possibility of
> being
> uninitialized, while variant doesn't. (for the later, nil_t is just
> another possible value).
> 
> In this regard optional<> is more handy for its intended usage.

Hmmm, I'm not sure if I agree with this. T can very well be
uninitialized in the variant when nil_t is in effect. Then
nil_t can just be struct nil_t {}; which costs nothing to initialize.
Why is optional "more handy" in this regard?

Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread David Abrahams
"Joel de Guzman" <[EMAIL PROTECTED]> writes:

> - Original Message - 
> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
>
>
>> optional<> is trying to model using C++ a concept that
>> it is not really covered by the language, that of uninitialzed values.
>> It uses pointer semantics *just* because pointers are the only sort of
>> C++ objects which has a clear uninitialized state.
>
> Hi,
>
> Probably a dumb question but allow me to ask anyway:
>
> Wouldn't a more generic variant class do what the 
> optional is trying to do? I feel that optional is just a variant
> in disguise. Correct me if I'm wrong.

Someone once said that if a theorem in Physics involves numbers other
than zero, 1, or infinity, it's lacking in purity.

optional captures the zero/one distinction, which, as its analogy to
pointers makes clear, is a very useful one.  A type which can contain
any number of different types would have a much more complicated
interface.  Maybe it's just a different library?

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "Joel de Guzman" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 5:21 PM
Subject: Re: [boost] Formal review: Optional library


>
> - Original Message -
> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
>
>
>
> > optional<> is trying to model using C++ a concept that
> > it is not really covered by the language, that of uninitialzed values.
> > It uses pointer semantics *just* because pointers are the only sort of
> > C++ objects which has a clear uninitialized state.
>
> Hi,
>
> Probably a dumb question but allow me to ask anyway:
>
> Wouldn't a more generic variant class do what the
> optional is trying to do? I feel that optional is just a variant
> in disguise. Correct me if I'm wrong.
>
The difference is that optional<> *explicitly* deals with the possibility of
being
uninitialized, while variant doesn't. (for the later, nil_t is just
another possible value).

In this regard optional<> is more handy for its intended usage.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 4:26 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > I understand your reasoning, but what do you suggest?
>
> I suggest that we need not give much weight to optional when
designing
> optional's interface.

I see.
>
> > Leaving optional inherently unsafe?
>
> Unsafe? The conversion from optional to bool might be confusing, but
> it's not inherently unsafe.
>
I don't know.
Isn't it unsafe the fact that you can mistakenly forget to write '*' and get
the initialized state instead of the value? (now you get a compiler error)

I don't know.
I'd like to see others opinions.

Should optional<> have safe_bool which would allow possibly unintended
conversions from optional to bool?
Will it be enough to put appropriate warnings and recommendations on the
documentation?

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 12:43 PM
Subject: Re: [boost] Formal review: Optional library


> OK, I've been thinking about the interface a bit more and want to voice
> some other opinions.  First, why were pointer semantics chosen at all?
> Why couldn't you have gone with value semantics?
>
> optional foo()
> {
>//...
> }
>
> void bar(int value)
> {
>//...
> }
>
> optional res = foo();
> if (res.initialized())
>bar(res);
>
> I can think of a few reasons, but want to hear about them from the
> designer, and want to see the rationale documented.
>
Fair enough.
Originally, optional<> had value semantics, so I used it pretty much like
in the examples you've shown.
But I had problem: since it had value semantics, it was perfectly OK to
write:

optional x = foo();
if ( x == 0 )
  some();

Or even:  if ( x ) some(x);

Meaning "compare the 'value' of x against 0".

Therefore, I needed something explicitely different to test
if it was initialized or not:

optional x = foo();
if ( x.initialied() )
  some(x);

But if I wrote:

optional x = foo();
if ( x )
  some(x);

it really looked as if it were testing if 'x' is initialized
while it was acutally comparing the 'x' value against 0.

Eventually, I realized that value semantics are not really appropiate to
deal
with unininitialized states since it blurs the distinction between
testing against other values and testing whether it is initialized or not.
So I wonder which other semantics would deal with it properly,
and pointers poped into my mind quickly.

> Now, assuming we stick with pointer semantics, let's make this as close to
> the "normal" smart pointer interface as possible:
>
>
> template 
> class optional
> {
> public:
>optional();
>explicit optional(T const& value);
>optional(optional const& other);
>template 
>   optional(optional const& other);
>~optional();
>
>T& operator*() const;
>T* operator->() const;
>T* get() const;
>// T* release();
>void reset();
>void reset(T const& value);
>operator unspecified-bool-type() const;
> };
>
>
This interface is greatly simplified mainly because
my interface offers deep-constantness:

T const* peek() const ;
T*   peek();
T const& operator*() const;
prxy operator*() ;

instead of:

T* peek() const ;
T& operator*() const;

The proxy is needed *only* to achieve deep-constantness.
If this feature weren't introduced, my interface would have looked
just like yours.

> Semantics and rationale:
>
> optional()
>
>Constructs an "uninitialized" optional.
>
> explicit optional(T const& value)
>
>Constructs an optional initialized to value through copy construction.
>
> optional(optional const& other)
>
>Copy constructs an optional using the value-type's copy constructor.
>
> template  optional(optional const& other)
>
>Allows copy construction from "compatible" optionals (optionals with
> value types that can be used for constructing this optional's value
> type).  I'm not sure how important this one is for optional, to be
> honest.
>
I've never needed to convert between optinals.
On a related note, if deep-constantess is not supported
(as in your interface), an implicit conversion from
optional to optional is needed because
the user will have to use  to attach constantess
to the value.


> ~optional()
>
>If the optional is initialized, calls the value-type's destructor.
>

Why isn't assignment supplied?


> T& operator*() const
>
>If the optional is not initialized, results in undefined behavior.
> Otherwise, returns a reference to the value.
>
> T* operator->() const
>
>If the optional is not initialized, results in undefined behavior.
>
> T* get() const
>
>If the optional is not initialized, returns 0.  Otherwise, returns a
> pointer to the value.
>
>Rationale: This provides the interface to determine whether or not the
> optional has been initialized.  Nothing else is required.
>
> // T* release()
>
>Rationale: Since ownership can not be transferred, this interface is
> not supported.
>
> void reset()
>
>If the optional is initialized, calls the destructor and sets the
> optional as "uninitialized".
>
>Rationale: Provides an interface to put the optional back into an
> "uninitialized" state.
>
> void reset(T const& other)
>
>If the optional is initialized, calls the destructor. 

Re: [boost] Formal review: Optional library

2002-12-10 Thread Joel de Guzman

- Original Message - 
From: "Fernando Cacciola" <[EMAIL PROTECTED]>



> optional<> is trying to model using C++ a concept that
> it is not really covered by the language, that of uninitialzed values.
> It uses pointer semantics *just* because pointers are the only sort of
> C++ objects which has a clear uninitialized state.

Hi,

Probably a dumb question but allow me to ask anyway:

Wouldn't a more generic variant class do what the 
optional is trying to do? I feel that optional is just a variant
in disguise. Correct me if I'm wrong.

Cheers,
Joel de Guzman
[EMAIL PROTECTED]
http://www.boost-consulting.com


___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> I understand your reasoning, but what do you suggest?

I suggest that we need not give much weight to optional when designing
optional's interface.

> Leaving optional inherently unsafe?

Unsafe? The conversion from optional to bool might be confusing, but
it's not inherently unsafe.

> with a strong remark on the
> documentation that you should been using optional in the first
place?

This would be a good idea.

> Or specializing optional, perhaps, with a empty definition so that
it
> is explicitly banned?

No, as you point out, this would create problems when generic code that uses
optional receives T=bool. But generic code wouldn't expect the conversion
from optional to bool to yield the value of the optional, right?

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread William E. Kempf

Fernando Cacciola said:
>> Fernando Cacciola said:
>> > "William E. Kempf" <[EMAIL PROTECTED]> wrote in message
>> >> * I believe there should be an "optional& operator=(T const& v)".
>> >>
>> > This would break the pointer-semantics:
>> >
>> > optional opt ;
>> >
>> > opt = 3 ;
>> >
>> > instead of
>> >
>> > *opt = 3 ;
>> >
>> > as it is currently the required syntax.
>>
>> Things get a little confusing here since optional<> is a smart pointer
>> of sorts, but it's assigned values not pointers.
>
> This might lead to confusion.
> optional<> is not really a smart-pointer sort of thing.
> It has similarities, but *significant* differences as well.
> I think than shaping optional<> as a smart pointer blurs
> those important differences.
> The most important difference, as I see it, is that a smart pointer
> wraps 'a pointer' which 'points to an object'.

I'm not sure I agree with this.  A smart pointer to me is simply an object
whose interface mimics a pointer.  Granted, this is the first case I've
ever seen where the implementation doesn't wrap a real pointer, but I'm
not at all sure this makes any difference here.  If it does, then I don't
think the pointer interface should be used at all and you should consider
value semantics instead.

> optional<> is trying to model using C++ a concept that
> it is not really covered by the language, that of uninitialzed values.
> It uses pointer semantics *just* because pointers are the only sort of
> C++ objects which has a clear uninitialized state.

I think that's flawed logic.  There are a lot of C++ objects I've seen
(with out the generic reusable design we get with optional) that deal with
an "uninitialized state".  Granted, they fail to truly not initialize the
data like optional does, instead default initializing the data, but the
idea is still the same.  The value of the data is not gauranteed to
fullfill any invariants when the "uninitialized" flag is true.  So,
pointers aren't the only examples available.  And even if they were, that
still wouldn't necessarily mean they'd be the correct interface in this
case.

But I do see reasons to want to keep with a smart pointer design and am
not (necessarily) trying to convince you to switch to value semantics. 
All I'm saying is that if we retain a smart pointer design, we should be
faithful to that decision.

> That's why it hands you a pointer to the value, because you can test the
> pointer
> for NULL; but that's it.
> IOWs, the pointer returned by optional is conceptually a handle, not a
> pointer.
> That's why I like the member function peek() much better than get().

I still much prefer the standard get(), even if I bought into the rest of
the rationale.  It's what people expect because of std::auto_ptr.

>> As long as there's a
>> constructor taking a value, it seems logical to me there should be an
>> assignment taking a value.
>
> There is an asymmetry here, certainly.
> Originally, optional<> did not have a constructor taking a value,
> precisely in order to keep it symmetry, but it was argued that it
> cluttered the interface too much, so I eventually bent my mind and added
> the constructor.

As did I in the interface I proposed elsewhere.  My complaint wasn't
actually the lack of an operator=(), but of the lack of any way to
reassign the value in an efficient and uniform manner.

>> But I won't argue this one too much.  But with
>> out the assignment I think it becomes more imperative to add a reset()
>> that allows you to modify the value with out the need for a temporary
>> optional<>.
>>
> I don't know.
> I'm generally not too fond of small-convenient-member-functions
> which offer a shortcut-functionality which blurs the conceptual
> uniformity of the design.

But that's not the case here.  The current interface provides no way to
_efficiently_ change the value.  (That is, with out regard for whether or
not the optional has been initialized.)

> Currently, optional<> is not a designed as a container,
> it wraps a value, true, but it does not 'contain it'
> in the sense that you cannot put it in and take it out.
> reset() would actually shape optional<> more like a container
> because it would amount to 'replace the value'.

Change the wording to "change the value" and I think you see the need, and
I think reset() conveys this.

> I know that since you construct an optional with a value, and since you
> can turn an optional into the uninitialized state, it is actually
> 'similar' to a container, but there is a difference: when you construct
> an optional<> with a value, the optional uses the value to initialize
> its own value, it is not 'takinging it' (it isn't containing it).
> Similarly, when you 'uninitialize' an optional, it is destroying its
> value, but it is not taking it out (otherwise uninitialize would return
> the previosu value).

I think you're trying to convey too much with the naming, with the result
being that the interface is actually _less_ understandable.

>> > If I manage to make

Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 3:33 PM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > > I don't think that optional is an important use case (outside of
> > > generic contexts) since optional is simply a tri-state type with
> an
> > > inconvenient interface.
> > >
> > Good point. I've been using optional long before tribool existed.
> > Now I might replace optional with tribool;  but, a user still
> > can have optional.
>
> But what is gained by using optional instead of
>
> enum optional_bool { uninitialized, true_, false_ };
>
> ?
>
> Especially if you take into account that with the enum you can use
> descriptive identifiers. It's a good idea to use enums in interfaces even
> for non-optional bools when the meaning of 'true' isn't immediately
> apparent.
>
I understand your reasoning, but what do you suggest?
Leaving optional inherently unsafe? with a strong remark on the
documentation that you should been using optional in the first place?
Or specializing optional, perhaps, with a empty definition so that it
is explicitly banned?

It worries me that any of the options above will create problems when
optional is used generically, as in optional.

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola

- Original Message -
From: "Anthony Williams" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 9:46 AM
Subject: Re: [boost] Formal review: Optional library


> Fernando Cacciola writes:
>  >
>  > - Original Message -
>  > From: "Glen Knowles" <[EMAIL PROTECTED]>
>  > To: "'Boost mailing list'" <[EMAIL PROTECTED]>
>  > Sent: Monday, December 09, 2002 6:42 PM
>  > Subject: RE: [boost] Formal review: Optional library
>  >
>  >
>  > > From: Fernando Cacciola [mailto:[EMAIL PROTECTED]]
>  > > >>
>  > > >> * I'm unsure about the presence of "initialized()".  On the one
hand,
>  > the
>  > > >> duplication in features (compared to "get/peek() == 0") is
something I
>  > > >> think designs should generally avoid.  On the other hand, this
name is
>  > > >> more meaningful for what precisely "get/peek() == 0" signifies.  I
>  > guess
>  > > >> I'm +0 on this one.
>  > > >>
>  > > >To be honest, I dislike it too :-)
>  > > >But some people found the alternative spellings ugly,
>  > > >so I figured that a member function would make them happy.
>  > >
>  > > How about using !empty() instead of initialized() ?
>  > >
>  > The problem William was raising is not about the particular name of the
>  > member-function: empty() or initialized(); but about having a(nother)
>  > member-function to do a job which is already covered by other parts of
the
>  > interface.
>  > (note that there is no empty() member function in optional<>)
>  >
>  > OTOH, whether to have 'empty' or 'initialized'... well, I prefer
>  > 'initialized', but that's mainly a matter of personal taste I think.
>
> empty() is analogous to containers.
>
Yes, and that's why I didn't call it empty() :-)
See my reponse to William

> Given empty(), I see no need for peek() _and_ get_value() --- if you can
get a
> reference to the value, you can get its address, if necessary.
>
Only if the optional<> is initialized.
peek() returns NULL in case the optional<> is uninitialized,
saving the user from having to test for it separately.

In fact, the whole point of pointer semantic is to allow the user to
deal with the uninitialized case conveniently, without having to
test empty() (or whatever) explicitely all the time.

>
> I prefer the member interface to the non-member interface, in this
instance.
>
I don't. Member functions are tightly coupled with class types.
As I said earlier, the usages of optional<> easely allows the code to
replace
optional<> with bare pointers.
This wouldn't be possible if member functions were used.

> You might like to use the techniques from my StrongStorage class (see the
> boost files section on yahoo) to ensure integrity in the face of
exceptions
> --- StrongStorage actually provides a very minimal implementation of
> optional<>.
>
I definitely will need something to increase exception safety in optional<>.
That could be your technique (the double-buffer right?), or Eric Friedman's
Move Library
which he will submit eventualy.
At this point it appears to me that Eric's move traits would be better on
average because
it won't require double storage; though I know your technique, OTOH,
gives the strong guarantee in *all* cases and not just the average.
But we'll have time to talk about this once Eric's move library is on the
table.


> In any case, I say ACCEPT the library.

Great!

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Peter Dimov
From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > I don't think that optional is an important use case (outside of
> > generic contexts) since optional is simply a tri-state type with
an
> > inconvenient interface.
> >
> Good point. I've been using optional long before tribool existed.
> Now I might replace optional with tribool;  but, a user still
> can have optional.

But what is gained by using optional instead of

enum optional_bool { uninitialized, true_, false_ };

?

Especially if you take into account that with the enum you can use
descriptive identifiers. It's a good idea to use enums in interfaces even
for non-optional bools when the meaning of 'true' isn't immediately
apparent.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola
- Original Message -
From: "Peter Dimov" <[EMAIL PROTECTED]>
To: "Boost mailing list" <[EMAIL PROTECTED]>
Sent: Tuesday, December 10, 2002 9:23 AM
Subject: Re: [boost] Formal review: Optional library


> From: "Fernando Cacciola" <[EMAIL PROTECTED]>
> > The conversion to bool for a smart pointer unambiguously refers to the
> > NULL state of the pointer wrapped.
> > In the case of optional, a conversion to bool will be ambiguous in those
> > cases were the wrapped T in optional<> is bool itself.
>
> On the other hand, it would enable the useful idiom
>
> if(optional pt = get_optional_T())
> {
> // use *pt
> }
>
Yes, it would.

> I don't think that optional is an important use case (outside of
> generic contexts) since optional is simply a tri-state type with an
> inconvenient interface.
>
Good point. I've been using optional long before tribool existed.
Now I might replace optional with tribool;  but, a user still
can have optional.
I wouldn't specialize optional for reasons I gave before.
Though I see that you've found a really useful idiom, I still not sure it
worth
the potential danger. (see my response to William)

Fernando Cacciola

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Formal review: Optional library

2002-12-10 Thread Fernando Cacciola
- Original Message -
From: "William E. Kempf" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Monday, December 09, 2002 7:48 PM
Subject: Re: [boost] Formal review: Optional library


>
> Fernando Cacciola said:
> > "William E. Kempf" <[EMAIL PROTECTED]> wrote in message
> >> * I believe there should be an "optional& operator=(T const& v)".
> >>
> > This would break the pointer-semantics:
> >
> > optional opt ;
> >
> > opt = 3 ;
> >
> > instead of
> >
> > *opt = 3 ;
> >
> > as it is currently the required syntax.
>
> Things get a little confusing here since optional<> is a smart pointer of
> sorts, but it's assigned values not pointers.

This might lead to confusion.
optional<> is not really a smart-pointer sort of thing.
It has similarities, but *significant* differences as well.
I think than shaping optional<> as a smart pointer blurs
those important differences.
The most important difference, as I see it, is that a smart pointer wraps
'a pointer' which 'points to an object'.
That is, a smart pointer carries two things: a pointer value + an object
value.
You handle the pointer value via get(),reset(), etc...
You handle the object value via operators *() and ->().
But optional<>, OTOH, wraps *only* an object value.
It does not 'contain a pointer' as a smart pointer does.

Now, optional<> do has a member function that returns a pointer
to its wrapped object, but this is a pointer which is actually
intended to allow you to access the value from within optional<>,
while at the same time let you handle the uninitialized state
conviently.

optional<> is trying to model using C++ a concept that
it is not really covered by the language, that of uninitialzed values.
It uses pointer semantics *just* because pointers are the only sort of
C++ objects which has a clear uninitialized state.
That's why it hands you a pointer to the value, because you can test the
pointer
for NULL; but that's it.
IOWs, the pointer returned by optional is conceptually a handle, not a
pointer.
That's why I like the member function peek() much better than get().

> As long as there's a
> constructor taking a value, it seems logical to me there should be an
> assignment taking a value.

There is an asymmetry here, certainly.
Originally, optional<> did not have a constructor taking a value,
precisely in order to keep it symmetry, but it was argued that it
cluttered the interface too much, so I eventually bent my mind and
added the constructor.

> But I won't argue this one too much.  But with
> out the assignment I think it becomes more imperative to add a reset()
> that allows you to modify the value with out the need for a temporary
> optional<>.
>
I don't know.
I'm generally not too fond of small-convenient-member-functions
which offer a shortcut-functionality which blurs the conceptual uniformity
of the design.
Currently, optional<> is not a designed as a container,
it wraps a value, true, but it does not 'contain it'
in the sense that you cannot put it in and take it out.
reset() would actually shape optional<> more like a container
because it would amount to 'replace the value'.

I know that since you construct an optional with a value, and since you
can turn an optional into the uninitialized state, it is actually 'similar'
to a container, but there is a difference: when you construct an optional<>
with a value, the optional uses the value to initialize its own value, it is
not 'takinging it' (it isn't containing it).
Similarly, when you 'uninitialize' an optional, it is destroying its value,
but it is not taking it out (otherwise uninitialize would return the
previosu value).


> >> * I think "peek()" should be named "get()".  Despite it's unusual (and
> >> needed) use, this is a form of a smart pointer, and should follow the
> >> same naming conventions that people have grown accustomed to through
> >> std::auto_ptr and the Boost smart pointers.
> >>
> > Fair enough.
> > I'm actually trying to vouch for my peek/acquire idiom here.
> > Essentially, the name 'peek()' is intended to convey the fact that the
> > pointer
> > points to a managed object and that the ownership is not being
> > transfered along with the pointer (as oposed to acquire()).
>
> Where did acquire() come from?

See my response to Dirk Gerrits.

>
> > If I manage to make the idiom known enough, the user will know that he
> > can't delete the pointer and that the pointer can be used only
> > as long as the 'source'

Re: [boost] Formal review: Optional library

2002-12-10 Thread William E. Kempf
OK, I've been thinking about the interface a bit more and want to voice
some other opinions.  First, why were pointer semantics chosen at all? 
Why couldn't you have gone with value semantics?

optional foo()
{
   //...
}

void bar(int value)
{
   //...
}

optional res = foo();
if (res.initialized())
   bar(res);

I can think of a few reasons, but want to hear about them from the
designer, and want to see the rationale documented.

Now, assuming we stick with pointer semantics, let's make this as close to
the "normal" smart pointer interface as possible:

template 
class optional
{
public:
   optional();
   explicit optional(T const& value);
   optional(optional const& other);
   template 
  optional(optional const& other);
   ~optional();

   T& operator*() const;
   T* operator->() const;
   T* get() const;
   // T* release();
   void reset();
   void reset(T const& value);
   operator unspecified-bool-type() const;
};

Semantics and rationale:

optional()

   Constructs an "uninitialized" optional.

explicit optional(T const& value)

   Constructs an optional initialized to value through copy construction.

optional(optional const& other)

   Copy constructs an optional using the value-type's copy constructor.

template  optional(optional const& other)

   Allows copy construction from "compatible" optionals (optionals with
value types that can be used for constructing this optional's value
type).  I'm not sure how important this one is for optional, to be
honest.

~optional()

   If the optional is initialized, calls the value-type's destructor.

T& operator*() const

   If the optional is not initialized, results in undefined behavior. 
Otherwise, returns a reference to the value.

T* operator->() const

   If the optional is not initialized, results in undefined behavior.

T* get() const

   If the optional is not initialized, returns 0.  Otherwise, returns a
pointer to the value.

   Rationale: This provides the interface to determine whether or not the
optional has been initialized.  Nothing else is required.

// T* release()

   Rationale: Since ownership can not be transferred, this interface is
not supported.

void reset()

   If the optional is initialized, calls the destructor and sets the
optional as "uninitialized".

   Rationale: Provides an interface to put the optional back into an
"uninitialized" state.

void reset(T const& other)

   If the optional is initialized, calls the destructor.  Copy constructs
the value in place.

   Rationale:  Provides an interface to set the value for an optional in
an "uninitialized" state.  If there's some meta-magic that would allow
you to use the value's operator=() if it has one this could be used as
an optimization instead of the destruct/construct idiom.

operator unspecified-bool-type() const

   Returns an unspecified type (safe-bool idiom) that's convertable to
bool, with a true value indicating the optional is not in an
uninitialized state.

   Rationale:  Allows for easier testing for the "uninitialized" state,
especially for testing through assignments:

   if (opt = foo())

This interface is nearly identical to std::auto_ptr, and as such should be
instantly understandable by most C++ programmers.  It provides all of the
functionality present in the currently proposed interface, yet doesn't
provide unnecessary duplicate interfaces or any use cases that should be
ambiguous.

William E. Kempf



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



  1   2   >