Boost logo

Boost :

Subject: Re: [boost] compact_optional -- prompting interest
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2015-09-27 16:45:21


On Sun, Sep 27, 2015 at 4:23 AM, Andrey Semashev <andrey.semashev_at_[hidden]>
wrote:
>
> If the empty state of intrusive_optional means the governed object is not
> constructed then the usability of this tool will be significantly reduced.
> Defining the policy of empty state detection would require intricate
> knowledge of behavior and binary layout of the adapted type, including ABI
> details such as padding and vtable/virtual inheritance table pointers. For
> instance, you wouldn't be able to use intrusive_optional with std::string.

Right, which is why you wouldn't use such an an "intrusive_optional"
template in that specific case (if you made a string type you certainly
could use it, though). I'm not saying intrusive_optional would replace your
template, I'm just agreeing with others that if you do use one of the
existing, valid values for the type, it's not really the same kind of
abstraction as optional, even though it is useful, so it should probably
just have a different name. Places where something like intrusive_optional
(which is similar to your type, but more akin to optional) are useful are
with types that you have control over.

For instance, I have a "card" type that I use for representing one of 52
possible playing cards. It takes up a byte, even though a byte can hold
more that 52 different values. If I put a card in an optional as-is, then
it's occupying extra space for the discriminator. I'd like to use optional
to represent "not-a-card" because had I baked a "not-a-card" value into the
original type itself, then any function that takes an actual card would
need an additional precondition and I'd likely want to assert to make sure
that the card is valid. With an intrusive_optional abstraction, it makes it
easy to just use the spare storage in the byte in order to represent
not-a-card only when it is needed, and it takes up no extra storage than
what the base abstraction does.

This is a common desire when making types -- you often want a never empty
guarantee so you do not wish to add an empty state to your underlying type.
Ideally you could take advantage of optional in a way that would let you
get an optional instance of your type without taking up extra space.
Specializing optional is one way to do this, but is complicated, and really
you only should need to do it via a much simpler customization point.

Anyway, this is on a tangent. I am in favor of your type, I just don't
think "optional" should be in the name, since your underlying object is:

A) Still constructed when in the "none" state
B) Uses a normally valid value to represent "none"

It's pretty weird that:

//////////
compact_optional<A. /*...*/> foo = A();
A& underlying = *foo;
underlying.bar();
// foo could technically be "none" now
// even though an "A" is constructed and
// has a valid value. This is a different
// kind of abstraction than an optional.
//////////

-- 
-Matt Calabrese

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