|
Boost : |
From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-11-03 14:18:01
On Saturday 03 November 2001 03:27, you wrote:
> Actually, I think that there is a third option which would be the
> best long term solution.
> The fundamental problem is that the standard disallows non-PODs in
> unions, hence the need for creating a POD with the same alignment via
> alignment_traits. The language definition could, though, be easily
> extended to allow class types directly in union definitions (perhaps
> requiring a POD as the first (initialised) member). This would remove
> the need for std::aligment_traits<>::align_t.
Unfortunately, then unions need destructors. Those destructors have to call
the destructor of the currently valid member. To know which member is valid,
the size of a union has to be increased to hold a tag. We have now allocated
the storage required for a discriminated union, but we don't yet have the
syntax for checking which member is valid; so we end up extending the
language further to include that syntax. Now unions in C++ differ in
size/layout from unions in C, and we have a whole host of new C compatibility
problems cropping up.
I'm not convinced it's an easy extension.
> (In fact, I vaguely remember reading somewhere on the web that an
> even more extensive upgrade of unions to allow class types was being
> considered for the next language standard anyway. Does anyone have
> any details on that?)
>
> Failing that however, I agree that a standard
> alignment_traits<>::align_t and ::value is the best library solution.
I take the opposite view on this. We have unions already, and I think we're
stuck with the current semantics for the foreseeable future. They're not
typesafe and they can't deal with all C++ types, so they don't fit well at
all into a high level programming language. It seems that the logical step is
toward a higher-level construct, such as a descriminated union that would
naturally be able to handle any type and would be type safe. Should it be
implemented as a language feature or as a library component?
As a language feature, it'll most likely have a clean syntax and well-defined
semantics. A new keyword will likely be introduced for the construct, which
will break compatibility with C++98. Adoption will probably again be slow -
we can't even rely on relatively simple features being implemented corrected
(partial specialization) 3 years after we had a standard, so how long would
it be until this discriminated union construct becomes mainstream? When would
it be used, e.g., in a Boost library without workarounds? Languages move
slowly, and each feature impacts the entire language in ways that won't be
known for a long time.
As a library feature, we might have to sacrifice some syntax. Instead of:
variant Expression {
AddExpression add;
MulExpression mul;
Variable var;
};
we might have:
typedef std::variant< tagged<Add, AddExpression>,
tagged<Mul, MulExpression>,
tagged<Var, Variable> > Expression;
However, we gain in many other areas. Semantics are still well-defined,
adoption can be very fast (most likely, just replace "namespace boost" with
"namespace std"), and there is no impact on the language.
So back to alignof/alignment_traits/etc. The path of minimal impact would be
to provide alignment_traits with some language support to get the "value" and
"align_t" fields. This can't be done complete in a library, but by placing it
in the context of a library we get language support without new syntax or any
language interactions.
Unions have horrible semantics, but we're stuck with them for C
compatibility. So we extend the notion by introducing a new library component
that fits better with C++ semantics, using the underlying C version (since
we're stuck with it anyway). This isn't a new concept - it's precisely what
the Boost Array and Function libraries do (fix C arrays to have C++-like
semantics and fix (member) function pointers to have C++-like semantics).
Doug
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk