Thread overview
Range with an alias parameter
Jan 30, 2019
Alex
Jan 30, 2019
Alex
Jan 31, 2019
Alex
January 30, 2019
Given this:

´´´
import std.experimental.all;

void main(){}

static assert(isInputRange!(ReturnType!(produceS!(42))[]));

auto produceS(size_t param)() { return S!param(); }
struct S(size_t param)
{
    //@disable this(this);
    auto opIndex() { return produceRange!(this); }
}

auto produceRange(alias source)(){ return Range!source(); }

struct Range(alias source)
{
    size_t front();
    void popFront();
    bool empty();
}
´´´

Why disabling copying of S removes the range property of Range?
January 30, 2019
On Wednesday, 30 January 2019 at 20:13:56 UTC, Alex wrote:
> Given this:
>
> ´´´
> import std.experimental.all;
>
> void main(){}
>
> static assert(isInputRange!(ReturnType!(produceS!(42))[]));
>
> auto produceS(size_t param)() { return S!param(); }
> struct S(size_t param)
> {
>     //@disable this(this);
>     auto opIndex() { return produceRange!(this); }
> }
>
> auto produceRange(alias source)(){ return Range!source(); }
>
> struct Range(alias source)
> {
>     size_t front();
>     void popFront();
>     bool empty();
> }
> ´´´
>
> Why disabling copying of S removes the range property of Range?

Ok... strange... it doesn't in fact... as this works:

´´´
import std.experimental.all;

void main()
{
    S!42 s;
    auto res = s[];
    static assert(isInputRange!(typeof(res)));
    res.front.writeln;
}

//static assert(isInputRange!(ReturnType!(produceS!(42))[]));

auto produceS(size_t param)() { return S!param(); }
struct S(size_t param)
{
    auto myParam(){return param; }
    @disable this(this);
    auto opIndex() { return produceRange!(this); }
}

auto produceRange(alias source)(){ return Range!source(); }

struct Range(alias source)
{
    size_t front(){return source.myParam;}
    void popFront();
    bool empty();
}
´´´
January 30, 2019
On 1/30/19 3:56 PM, Alex wrote:

> Ok... strange... it doesn't in fact... as this works:
> 
> ´´´
> import std.experimental.all;
> 
> void main()
> {
>      S!42 s;
>      auto res = s[];
>      static assert(isInputRange!(typeof(res)));
>      res.front.writeln;
> }
> 
> //static assert(isInputRange!(ReturnType!(produceS!(42))[]));

Apples and oranges :)

ReturnType!(produceS!(42)) is a TYPE, not a variable. When you apply the brackets, it's not calling your opindex, but rather changing it to an array. So let's make it clearer by saying:

alias T = ReturnType!(produceS!(42));

So now, your assert becomes:

static assert(isInputRange!(T[]));

Which, is not coming up as a valid range, because you can't copy the front value (this(this) is disabled).

In the other expression, you are first calling the index operator on an instance of the type, which returns a DIFFERENT type, and then asserting the type of that is an input range.

The equivalent (still using T) is:

static assert(isInputRange!(typeof(T.init[])));

replacing T with the original is:

static assert(isInputRange!(typeof(ReturnType!(produceS!(42)).init[])));

-Steve
January 31, 2019
On Thursday, 31 January 2019 at 02:41:00 UTC, Steven Schveighoffer wrote:
> Apples and oranges :)
>
> ReturnType!(produceS!(42)) is a TYPE, not a variable. When you apply the brackets, it's not calling your opindex, but rather changing it to an array. So let's make it clearer by saying:
>
> alias T = ReturnType!(produceS!(42));
>
> So now, your assert becomes:
>
> static assert(isInputRange!(T[]));
>
> Which, is not coming up as a valid range, because you can't copy the front value (this(this) is disabled).
>
> In the other expression, you are first calling the index operator on an instance of the type, which returns a DIFFERENT type, and then asserting the type of that is an input range.
>
> The equivalent (still using T) is:
>
> static assert(isInputRange!(typeof(T.init[])));
>
> replacing T with the original is:
>
> static assert(isInputRange!(typeof(ReturnType!(produceS!(42)).init[])));
>
> -Steve

Yeah... maybe, it was too much code for a single day yesterday... :P