Trying to use a template class with ranges

Steven Schveighoffer schveiguy at gmail.com
Thu Feb 6 15:21:46 UTC 2020


On 2/6/20 7:16 AM, mark wrote:
> I am starting on porting Python's difflib's sequence matcher to D.
> 
> I want to have a class that will accept two ranges whose elements are of 
> the same type and whose elements can be compared for equality.
> 
> How do I make a class declaration that specifies a (forward) range type 
> and an equality-supporting element type?
> 
> Here's what doesn't work:
> 
> class Diff(T, E) {
>      T a; // T should be a forward range of E elements
>      T b; // E elements must support == and !=
>          // This is a hash key=E element, value=slice of size_t
>      size_t[][E] b2j;
> 
>      this(T a, T b) {
>          this.a = a;
>          this.b = b;
>          chainB();
>      }
> 
>      void chainB() {
>          foreach (i, element; b)
>              b2j[element] ~= i;
>          // TODO
>      }
> }
> 
> unittest {
>      import std.stdio: writeln;
> 
>      writeln("unittest for the diffrange library.");
>      auto a = ["Tulips are yellow,", "Violets are blue,",
>                    "Agar is sweet,", "As are you."];
>      auto b = ["Roses are red,", "Violets are blue,",
>                    "Sugar is sweet,", "And so are you."];
>      auto diff = Diff(a, b);
> }
> 

1. If one template parameter depends 100% on the other, it doesn't need 
to be a parameter. i.e. I would do:

class Diff(T) {
    alias E = ElementType!T;
    ...
}

2. Class constructors do not support IFTI. You have to explicitly 
instantiate. To use IFTI, you need to create a factory function. i.e. to 
make the code above work, your ctor call should be Diff!(typeof(a)) 
(assuming you take the advice in 1).

But you can instead write a function to use IFTI:

auto makeDiff(T)(T r1, T r2) { return Diff!T(r1, r2); }

...

auto diff = makeDiff(a, b);

3. You should declare constraints signifying what types are valid. i.e.:

class Diff(T) if (
    isForwardRange!T // it's a forward range
    && is(typeof(T.init.front == T.init.front)) // elements are comparable
)

Might be good to put this constraint on the factory function too.

Note: is(typeof(...)) basically checks if the thing inside the typeof 
compiles.

-Steve


More information about the Digitalmars-d-learn mailing list