Thread overview
What does "(this This)" mean in member function templates?
Feb 12, 2018
Nathan S.
Feb 12, 2018
rikki cattermole
Feb 12, 2018
Nathan S.
Feb 12, 2018
Simen Kjærås
February 12, 2018
For example in std.container.rbtree:

---
    auto equalRange(this This)(Elem e)
    {
        auto beg = _firstGreaterEqual(e);
        alias RangeType = RBRange!(typeof(beg));
        if (beg is _end || _less(e, beg.value))
            // no values are equal
            return RangeType(beg, beg);
        static if (allowDuplicates)
        {
            return RangeType(beg, _firstGreater(e));
        }
        else
        {
            // no sense in doing a full search, no duplicates are allowed,
            // so we just get the next node.
            return RangeType(beg, beg.next);
        }
    }
---
February 12, 2018
On 12/02/2018 8:35 AM, Nathan S. wrote:
> For example in std.container.rbtree:
> 
> ---
>      auto equalRange(this This)(Elem e)
>      {
>          auto beg = _firstGreaterEqual(e);
>          alias RangeType = RBRange!(typeof(beg));
>          if (beg is _end || _less(e, beg.value))
>              // no values are equal
>              return RangeType(beg, beg);
>          static if (allowDuplicates)
>          {
>              return RangeType(beg, _firstGreater(e));
>          }
>          else
>          {
>              // no sense in doing a full search, no duplicates are allowed,
>              // so we just get the next node.
>              return RangeType(beg, beg.next);
>          }
>      }
> ---

https://dlang.org/spec/template.html#TemplateThisParameter
February 12, 2018
On Monday, 12 February 2018 at 08:35:05 UTC, Nathan S. wrote:
> For example in std.container.rbtree:
>
> ---
>     auto equalRange(this This)(Elem e)
>     {
>         auto beg = _firstGreaterEqual(e);
>         alias RangeType = RBRange!(typeof(beg));
>         if (beg is _end || _less(e, beg.value))
>             // no values are equal
>             return RangeType(beg, beg);
>         static if (allowDuplicates)
>         {
>             return RangeType(beg, _firstGreater(e));
>         }
>         else
>         {
>             // no sense in doing a full search, no duplicates are allowed,
>             // so we just get the next node.
>             return RangeType(beg, beg.next);
>         }
>     }
> ---

It's a template this parameter:
https://dlang.org/spec/template.html#template_this_parameter

Simply put, it gets the type of the 'this' parameter when the function is invoked, with all type modifiers. For a class A with a subclass B, 'This' would be B if called from B, and const(A) when called from const(A).

The type of the 'this' parameter is the statically known type, not the dynamic type. This creates some limitations, as shown below.

Some examples:

struct S {
   void foo(this This)() {
       writeln(This.stringof);
   }
}

class A {
    void foo(this This)() {
        writeln(This.stringof);
    }
    void bar() {
        foo();
    }
}

class B : A{}

unittest {
    S s;
    const shared S css;
    immutable S iss;
    s.foo(); // S
    css.foo(); // shared(const(S))
    iss.foo(); // immutable(S)
    B b = new B();
    A a = b;
    b.foo(); // B
    a.foo(); // A, since typeof(a) == A.
    b.bar(); // A, since bar() calls foo() in a context where the type of 'this' is A.
}

--
  Simen
February 12, 2018
On Monday, 12 February 2018 at 08:42:42 UTC, rikki cattermole wrote:
> https://dlang.org/spec/template.html#TemplateThisParameter

Cheers.