Should the "front" range primitive be "const" ?

Drone1h drone1h at gmail.com
Mon Mar 19 00:14:11 UTC 2018


First of all, thank you all for the replies. It has taken me some 
time to learn a bit more to be able to understand at least some 
parts of them. I have a further question below the quotes.

On Tuesday, 30 January 2018 at 01:20:09 UTC, Jonathan M Davis 
wrote:
> On Tuesday, January 30, 2018 01:05:54 Drone1h via 
> Digitalmars-d-learn wrote:

>> [...]
>> I am trying to implement a ("struct template" ? what is the
>> correct word ?) range that just forwards its primitives 
>> ("empty",
>> "front", "popFront") to another range, possibly with some very
>> limited filtering/alteration, as std.range.Take (just to 
>> learn).
>>
>> Initially, the "front" member function (property) used to be
>> declared "const", but that was not accepted when the underlying
>> range (denoted "R" in the code below) was 
>> std.stdio.File.ByChunk
>> ("Error: mutable method std.stdio.File.ByChunk.front is not
>> callable using a const object").
>> [...]

> If you want to put an attribute on it, inout is better, because 
> then it will work with any constness

I am not sure whether I can make it work with "inout" instead of 
"const". Perhaps I am missing something.

Here is my code:

     auto Take2 (R) (R r, size_t n)
     {
         import std.range.primitives;

         struct Result
         {
         private:
             R      _r;
             size_t _n;
             size_t _i;

         public:
             @property bool empty () const
             {
                 return _i >= _n || _r.empty;
             }

             @property auto ref front () const // Replace "const" 
with "inout" here ?
             {
                 return _r.front;
             }

             void popFront ()
             {
                 ++_i;
                 if (_i < _n)
                     _r.popFront ();
             }

             this (R r, size_t n)
             {
                 _r = r;
                 _n = n;
                 _i = 0;
             }
         }

         return Result (r, n);
     }

     unittest
     {
         import std.stdio;

         auto file = File ("Example", "rb");
         foreach (c; file.byChunk (0x100).Take2 (5))
             stdout.rawWrite (c);
     }

I get compile error:

     Error: mutable method `std.stdio.File.ByChunkImpl.front` is 
not callable using a `const` object

If I replace "const" with "inout" for the "front" function, i.e. 
"@property auto ref front () inout", I get similar error:

     Error: mutable method `std.stdio.File.ByChunkImpl.front` is 
not callable using a `inout` object

May I ask that you confirm that this is what you suggested ? 
Thank you.



> [...] const ranges are utterly useless, because they can't be 
> mutated and thus can't be iterated. [...]

I am considering a function that takes as parameter a (reference 
to) const range. It should be able to check whether the range is 
"empty" and, if not empty, it should be able to access the 
"front" element.

Now the caller of that function can rest assured that the 
function is not going to modify the range by "popFront".

The function might be more useful than a function that just takes 
as parameter a value (the result of "front") because it may be 
called with an empty range and it can detect that. This is 
similar to getting as parameter a (possibly null) pointer to a 
value instead of getting as parameter a value.

Therefore, it seems to me that a const range might be useful.

If you have already considered this and have actually seen 
one-step ahead of me, may I ask that you confirm, please ?



Thank you respectfully.



More information about the Digitalmars-d-learn mailing list