D does have head const (but maybe it shouldn't)
ag0aep6g
anonymous at example.com
Tue Dec 29 19:22:49 UTC 2020
On Tuesday, 29 December 2020 at 17:56:51 UTC, H. S. Teoh wrote:
> On Tue, Dec 29, 2020 at 05:13:48PM +0000, Petar via
> Digitalmars-d wrote:
>> On Tuesday, 29 December 2020 at 16:15:56 UTC, ag0aep6g wrote:
[...]
>> > The validity of the given solution might be arguable, and
>> > I'd be in favour of outlawing it. It's surprising that
>> > there's a type for which `const` means head const when it
>> > means transitive const for everything else. It's so
>> > surprising that even DMD trips over it
>> > (<https://issues.dlang.org/show_bug.cgi?id=21511>).
>>
>> Wow. The solution surprised me, even though in retrospect it's
>> obvious to me why it works (bugs in this area of the type
>> system have been know for more than a few years). I'd say
>> head-const is a very useful tool, but it's pretty obvious to
>> me that this shouldn't be a supported way to implement it.
>
> I don't see why this is considered head const, nor why this
> should be considered a bug. In the proposed solution `y` is not
> a value type but a delegate that wraps the reference to *x.
> Since x itself is non-const, this is perfectly valid, and the
> `const` in `const y` refers to the immutability of the delegate
> reference, not to the immutability of the wrapped reference.
How are you not just describing head const? A thing that is
itself const and refers to something mutable => head const.
You know how a dynamic array (or slice) is often described as a
pointer plus a length. Explanations to newbies often contain a
mockup struct like this:
struct Slice(E)
{
E* ptr;
size_t length;
}
Because that's what a slice is, right? And when the newbie starts
to think about it that way, things often fall into place for them.
Similarly, it makes sense to think of a delegate like this:
struct Delegate(C, R, P ...)
{
C* context_ptr;
R function(C* context_ptr, P params) funcptr;
R opCall(P params) { return funcptr(context_ptr, params); }
}
(Ignoring details like how the context pointer is actually
passed.)
Now, when you have a `const Delegate!(int, void, /* no parameters
*/)`, its `context_ptr` is also const and you cannot gain mutable
access to the referenced int. Because that's how `const` works in
D (for the most part). But that restriction does not apply to a
`const void delegate()` whose context pointer is an `int*`.
I think it would save us some headaches if delegates behaved like
the structs that they really are.
More information about the Digitalmars-d
mailing list