On Wednesday, 17 January 2018 at 10:36:44 UTC, Jonathan M Davis wrote:
D is quite useable without tail-const, but without it, ranges and const can't be used together. The solution that most of us have taken is basically to give up on const. Having tail-const would be better, but implementing it without language support is a royal pain and not the sort of thing that most of us are going to bother with. It's just easier to give up on const. It would be a _lot_ nicer if we could figure out how to cleanly add tail-const to the language.

Sadly, constness doesn't propagate in a straightforward way - the equivalent const type for Foo!(int, int) could be Foo!(int, const(int)), Foo!(const(int), int), or Foo!(const(int), const(int)), and there's no way to specify this. At least in theory, it might even be that the const version is an entirely different template instantiation, so even something like `struct Foo(T, inout U)` might not be good enough. We might decide not to support anything as weird as different template overload sets, though.

If we look at what we already have, the basic building block is std.traits.Unqual. What's needed is a hook for those cases where Unqual!(const(R!T)) shouldn't simply be R!T. If Unqual tested for a member, e.g. "Unqual", and returned that type, that's important parts of the issue solved.

"Unqual" would probably be on the form 'alias Unqual(this T) = Foo!(CopyTypeQualifiers!(T, Args));'.

The big thing missing after amending Unqual like this, is implicit conversion. Currently, const(Foo!T) is generally not implicitly convertible to Foo!(const(T)). Since D templates are complex beasts, again there's not necessarily a straightforward way to do this. Alias this is some help, but trying to get that to work I ran into https://issues.dlang.org/show_bug.cgi?id=18260.

At any rate, this is a topic for a DIP.

--
  Simen

Reply via email to