On Monday, 15 February 2016 at 22:48:16 UTC, Walter Bright wrote:
rears its head again :-)
Head Const is what C++ has for const, i.e. it is not
transitive, applies to one level only. D has transitive const.
What head const will do for us:
1. make it easy to interface to C++ code that uses const, as
currently it is not very practical to do so, you have to resort
to pragma(mangle)
2. supports single assignment style of programming, even if the
data is otherwise mutable
The downside is, of course, language complexity.
Straight up head-const is utterly useless IMHO. That's what Java
has. C++ has something far more complicated where any individual
piece (or pieces) of a pointer type can be declared const without
necessarily making the whole thing const. So, _that_ is what we'd
need to interact with C++, and it's a downright ugly feature
IMHO. Tail-const has some value, because it allows you to refer
to a const object with a mutable pointer or reference, whereas
head-const just makes things ugly. So, if it weren't for
interacting with C++, I would give a resounding "no" to this.
It's not even vaguely worth the complexity.
As for interoperability with C++, I don't know. Previously, you
stated that we weren't going to do things like support
interacting with C++ templates (aside from specific
instantiations which weren't typed as templates), because it
would mean putting a C++ compiler into D, which you didn't want
to do. But increasingly, it seems like you're heading in the
direction of doing that in an attempt to be able to have
fantastic C++ interoperability. On the one on hand, that seems
great, since being able to have your C++ code work with your D
code is great, but on the other, it seems like it's going to make
it so that D is contaminated by a lot of extra C++ muck just to
be able to interoperate. At some point, we either need to decide
that we're just not going to interoperate with C++ in some manner
and lose out on some capability, or we're going to need to fully
interoperate with C++ and pretty much put a C++ compiler in the D
compiler, and I'd prefer that we didn't go that far.
In this particular case, doesn't this really just come down to
mangling? It's undefined behavior in D to mutate a const object
(even if it was constructed as mutable), so we can't just slap D
const on C++ types and have that work, since the C++ code could
legally mutate the object. But since C++ considers it defined
behavior to mutate a const object by casting away const (or at
least it does in all but some very specific cases), can we just
get away with the D code treating D const as mutable? If so, then
it's purely a matter of mangling. And for that, we could do
something like add @cppconst or cppconst that the compiler
recognizes and which is only valid in extern(C++) declarations.
It would unfortunately have to be more than a simple attribute,
because it would have to apply to parts of a parameter's type
like C++'s const does (instead of the whole type at once), but if
it were implemented such that it was just something that went on
the extern(C++) function parameter types (or return types) for
mangling purposes, and the D code just treated it as mutable,
then it would at least restrict the muck to extern(C++).
Now, that does have the downside that the D code has no
protection against mutating a C++ object that the C++ code marks
as const (whereas while the C++ code can mutate, you at least
have to cast away const or use the mutable keyword first), but
that seems a whale of a lot better to me than trying to add
non-transitive const to D.
- Jonathan M Davis