|
Boost : |
From: Vesa Karvonen (vesa.karvonen_at_[hidden])
Date: 2001-08-29 19:47:24
From: "Douglas Gregor" <gregod_at_[hidden]>
> On Wednesday 29 August 2001 04:06, you wrote:
> > From: "Douglas Gregor" <gregod_at_[hidden]>
> > [... on optional ...]
> >
> > > I was recently working on a variant type that was intended to be created
> > > on the stack. I believe it is possible to do, though it isn't trivial
:).
> >
> > If I understand intention behind 'variant' correctly (I think of 'variant'
> > as a safe union that allows types with constructors and destructors) then
I
> > agree that it should be doable, but it is somewhat tricky to get it right:
> > - alignment
> > - exception safety
> > - safe/unsafe vswitch
>
> Alignment & exception safety are somewhat at odds.
^ with each other?
Could you elaborate?
> For instance, if I have a
> variants a and b and I want to swap them, it is tough (maybe impossible?) to
> do this in an exception-safe manner for pathological types.
It seems to me that 'swap', and probably all the other operations as well,
could easily be made exception safe if a 'move' operation would be guaranteed
to be exception safe:
// pseudo code
swap(variant t_type t, variant u_type u)
{
uninitialized t_type tmp;
// 3 exception safe moves:
tmp <- t; // effectively: "new (&tmp) t_type(t); t->~t_type();"
t <- u;
u <- tmp;
}
> Safe vswitch is the easy part :).
Yes, the only difficult part that I can see, at this point, is the syntax (of
both interface and implementation).
> > Now, if understand 'variant' correctly, then it seems to me that
'optional'
> > could be implemented something like this (without run-time overhead on an
> > ideal, but not "magical", compiler):
> >
> > template<class t>
> > struct optional
> > {
> > ...
> > private:
> > variant<t,void> v;
> > };
>
> Yes, though replace "void" with a real (but useless) type, like:
> struct unused {};
hmn... Do you mean that 'void' is an illegal parameter for 'variant'?
What do you think about the following table?
default: ctor | type | state
-----------------------+----------+--------+-------
optional<t> | lazy | t | empty
any | lazy | void | empty
Notes:
- 'optional' and 'any' can be 'empty'.
- At this point, to me, the (contained) type of 'optional<t>' always seems to
be 't'.
- 'any' has chosen to use 'void' as the type of the 'empty' state.
Questions:
- Can a 'variant' be 'empty'?
- What is the difference between 'variant' with and without 'void'?
I find it natural to think about 'variant' and 'void' like this:
default: ctor | type | state
-----------------------+----------+--------+-------
variant<t0,..,tn,void> | lazy | void | empty
variant<t0,..,tn> | strict | t0 | !empty (always)
[Having 't0' as the default type means just that the default type is chosen
using some simple convention.]
> > - 'variant<T,void>' seems very close to 'optional<T>'.
>
> It is very close semantically.
>
> > - 'variant' and 'any' might or might not make use of some pointer syntax.
>
> Pointer syntax doesn't really make sense for variant or any, because there
is
> no fixed return type for either. For optional and smart pointer, there is
> only one possible type. This I think justifies the syntactic differences.
I was mainly thinking of the following syntax:
!x ...meaning... x.empty()
if (x) ...meaning... if (!x.empty())
And possibly:
0 == x ...meaning... x.empty()
x == 0 ...meaning... x.empty()
However, the usefulness of the above syntax is not very clear. It seems to me
that 'vswitch' and 'cast' are the proper ways to use 'variant' and probably
'any', too.
Question:
- Is 'void' equivalent to 'empty'?
> > Intent:
> > - optional: signaling errors/uncomputable results, lazy
initialization
> > - variant: safe union ???
> > - any: typeless programming (it seems like a "boxed value")
> > - smart pointer: avoiding resource leaks/automatic finalization, exception
> > safety
>
> variant: discriminated union that also allows non-trivial
> constructors/destructors.
Ok.
> > Initialization:
> > - optional: lazy
> > - variant: ???
> > - any: lazy
> > - smart pointer: strict (or this is how I see the matter)
> >
> > Should 'variant' support lazy initialization? Parhaps variant<> should
> > support being left unitialized only if 'void' is one of the variant types.
>
> variant uses lazy initialization, though I can't say I like it much.
>
> > What about 'any'? Should it be 'any_or_none' or 'optional_any'?
>
> The name "any" seems reasonable...
Yes, I like it best, too. However, with my understanding of English, 'any'
does sort of imply that it is always something, which, in a sense, is not
true, because 'any' can be 'empty'.
> > Copy semantics:
> > - optional: value
> > - variant: value
> > - any: value
> > - smart pointer: reference, destructive copy or value (clone)
>
> Looks good. Not sure I agree with "destructive copy" or "value". I would
just
> say that smart pointers have reference semantics, but for objects with
> managed lifetimes.
Ideally (smart) pointers would simply have reference semantics, but there are
many "smart pointers" out there which make the case more interesting.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk