www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Returning range of inout objects from inout method

reply FreeSlave <freeslave93 gmail.com> writes:
I want to be able to return a range of const objects from the 
const object and a range mutable objects from the mutable object.

inout comes to mind, but not applicable in this case, because 
inout must be applied to the return type as whole, which does not 
make much sense for the range. Defining range of inout objects 
does not work too. See the example.

import std.range;
class A
{
     string name;
}

class B
{
     A[] _actions;
     ForwardRange!(inout(A)) byAction() inout { // can't instance 
this type
         import std.algorithm : filter;
         return inputRangeObject(_actions.filter!(a => a !is null 
&& a.name.length));
     }
}

So how can I achieve the intended effect without code 
duplication? (like making separate mutable and const versions of 
the method).
Jul 25 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/25/20 8:26 AM, FreeSlave wrote:
 I want to be able to return a range of const objects from the const 
 object and a range mutable objects from the mutable object.
 
 inout comes to mind, but not applicable in this case, because inout must 
 be applied to the return type as whole, which does not make much sense 
 for the range. Defining range of inout objects does not work too. See 
 the example.
 
 import std.range;
 class A
 {
      string name;
 }
 
 class B
 {
      A[] _actions;
      ForwardRange!(inout(A)) byAction() inout { // can't instance this type
          import std.algorithm : filter;
          return inputRangeObject(_actions.filter!(a => a !is null && 
 a.name.length));
      }
 }
 
 So how can I achieve the intended effect without code duplication? (like 
 making separate mutable and const versions of the method).
You can't exactly. The limitation that inout cannot be applied to a struct member is a crappy limitation, one which I wish I never advocated for. The only way to do this without code duplication (but with generated code duplication) is to template the byAction function on the type of `this`: auto byAction(this This)() { /* same implementation */ } Note that this ONLY works if your base range type is an array. If you have a custom range type, you need to parameterize that based on the constness of `This`. -Steve
Jul 25 2020
parent reply FreeSlave <freeslave93 gmail.com> writes:
On Saturday, 25 July 2020 at 14:19:15 UTC, Steven Schveighoffer 
wrote:
 The only way to do this without code duplication (but with 
 generated code duplication) is to template the byAction 
 function on the type of `this`:

 auto byAction(this This)() { /* same implementation */ }

 Note that this ONLY works if your base range type is an array. 
 If you have a custom range type, you need to parameterize that 
 based on the constness of `This`.

 -Steve
Thanks. I thought this template is useful only in inheritance. Is constness of member function inferred automatically in this case?
Jul 25 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/25/20 3:16 PM, FreeSlave wrote:
 On Saturday, 25 July 2020 at 14:19:15 UTC, Steven Schveighoffer wrote:
 The only way to do this without code duplication (but with generated 
 code duplication) is to template the byAction function on the type of 
 `this`:

 auto byAction(this This)() { /* same implementation */ }

 Note that this ONLY works if your base range type is an array. If you 
 have a custom range type, you need to parameterize that based on the 
 constness of `This`.
Thanks. I thought this template is useful only in inheritance. Is constness of member function inferred automatically in this case?
In this case, yes. I don't know actually if this is documented. -Steve
Jul 25 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/25/20 4:07 PM, Steven Schveighoffer wrote:
 On 7/25/20 3:16 PM, FreeSlave wrote:
 On Saturday, 25 July 2020 at 14:19:15 UTC, Steven Schveighoffer wrote:
 The only way to do this without code duplication (but with generated 
 code duplication) is to template the byAction function on the type of 
 `this`:

 auto byAction(this This)() { /* same implementation */ }

 Note that this ONLY works if your base range type is an array. If you 
 have a custom range type, you need to parameterize that based on the 
 constness of `This`.
Thanks. I thought this template is useful only in inheritance. Is constness of member function inferred automatically in this case?
In this case, yes. I don't know actually if this is documented.
It should be now. https://github.com/dlang/dlang.org/pull/2835 -Steve
Jul 25 2020