On Tuesday, January 30, 2018 07:49:28 H. S. Teoh via Digitalmars-d-learn wrote: > On Tue, Jan 30, 2018 at 08:54:00AM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote: > > On 1/29/18 8:20 PM, Jonathan M Davis wrote: > [...] > > > > If you want to put an attribute on it, inout is better, because then > > > it will work with any constness, but in general, I'd suggest just > > > avoiding the use of const or immutable altogether when dealing with > > > ranges. front can return a const element, and that will happen if > > > you use auto and whatever you're wrapping is const, but const ranges > > > are utterly useless, because they can't be mutated and thus can't be > > > iterated. As such, almost no code is ever going to have a range that > > > is anything but mutable, which means that having front be anything > > > but mutable is generally pointless. > > I think you're conflating a const range, which *is* pretty useless since > you can't iterate it, and a const .front, which only means "calling > .front will not change the state of the range". The latter is very > possible, and potentially useful. Well, there's also a .front that > returns a const element, which means "you can't change the current > element of the range". That's also possible, and useful.
Except that unless front returns by ref, it really doesn't matter whether front is const unless it's violating the range API, since front is supposed to return the same value until popFront is called (or if it's assigned a new value via a front that returns by ref). So, in practice, putting const on front really doesn't help you any, and it actually hurts you for range composability. > Simen has had some ideas recently about "head mutable" aka tail-const, > which could be a first step towards making const ranges, or rather > tail-const ranges, actually usable: > > https://forum.dlang.org/post/cpxfgdmklgusodqou...@forum.dlang.org > > tl;dr summary: > > (1) Ranges implement a standard method, tentatively called > opHeadMutable, that returns a head-mutable version of themselves. > For example, const(MyRange!T).opHeadMutable would return > MyRange!(const(T)). > > (2) Standard library functions would recognize opHeadMutable and use it > where needed, e.g., when you hand them a const range. > > (3) Profit. :-P I still need to look over what he's proposing in more detail - it's been proposed before (by Andrei IIRC) that one possible solution would be to add an operator for returning a tail-const version of a type, but no one has ever taken that idea anywhere. Personally, I'm getting to the point that I'd rather just avoid const than deal with any further complications for ranges. In principle, I like the idea of const, but in practice, it just constantly gets in the way, and I've rarely actually seen any benefit from it in either C++ or D. I can think of one time in my entire life where const has prevented a bug for me - which was when I got the arguments backwards to C++'s std::copy function. At least with immutable, you get implicit sharing and some optimization opportunities. In principle, const can get you some of the optimization opportunities but only in really restricted circumstances or circumstances where you could have used immutable and the code would have been the same (e.g. with int). - Jonathan M Davis