www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - template this parameters for constructors

reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
Template this parameters (
http://dlang.org/template.html#TemplateThisParameter) are extremely useful
for writing generic methods in base classes or interfaces that need to know
the static type of the object they're called on.

class Base
{
    string label;

    this(string label_)
    {
        label = label_;
    }

    string toString(this This_)()
    {
        return This_.stringof ~ "(`" ~ label ~ "`)";
    }
}

class Derived: Base
{
    this()
    {
        super("Hello, world!");
    }
}

unittest
{
    Derived d = new Derived();
    assert(d.toString() == "Derived(`Hello, world!`)");
}

Of course, this wouldn't work if the toString() was called from a Base
reference, instead of Derived.

After I tested this, immediately thought of the constructor. The
constructor of the base class is guaranteed to be called when constructing
a derived class, right? Even if the call is implicit, it still happens and
at the call site the concrete type being constructed is known, so in
theory, a template this parameter on the base class's constructor should
allow the base class to know the static type of the object being
constructed (which is immensely useful for implementing dynamic dispatch
classes).

class Base
{
    this(this This_)()
    {
        // Build a dispatch table using __traits(allMethods, This_)
    }

    void opCall(Payload_)(Payload_ payload_)
    {
        // Dynamically dispatch payload_ using the previously built
dispatch table.
    }
}

class Derived: Base
{
    // implicitly generated constructor will call the Base.this() and
implicitly give it the static type of Derived.
}

unittest
{
    Base b = new Derived;
    b(); // 100% transparent dynamic dispatch
}

Unfortunately, this is what DMD had to say about this:

C:\Users\g.gyolchanyan\Desktop\test.d(3): Error: found 'This_' when
expecting ')'
C:\Users\g.gyolchanyan\Desktop\test.d(3): Error: semicolon expected
following function declaration
C:\Users\g.gyolchanyan\Desktop\test.d(3): Error: Declaration expected, not
')'

It looks like DMD thinks I was gonna write a postblit constructor and I
guess the functionality is already there, but can't be reached due to a
parsing error.

Is there any change of this being fixed any time soon?

-- 
Bye,
Gor Gyolchanyan.
Feb 20 2013
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-02-20 15:37, Gor Gyolchanyan wrote:

 After I tested this, immediately thought of the constructor. The
 constructor of the base class is guaranteed to be called when
 constructing a derived class, right? Even if the call is implicit, it
 still happens and at the call site the concrete type being constructed
 is known, so in theory, a template this parameter on the base class's
 constructor should allow the base class to know the static type of the
 object being constructed (which is immensely useful for implementing
 dynamic dispatch classes).

 class Base
 {
      this(this This_)()
      {
          // Build a dispatch table using __traits(allMethods, This_)
      }

      void opCall(Payload_)(Payload_ payload_)
      {
          // Dynamically dispatch payload_ using the previously built
 dispatch table.
      }
 }

 class Derived: Base
 {
      // implicitly generated constructor will call the Base.this() and
 implicitly give it the static type of Derived.
 }

 unittest
 {
      Base b = new Derived;
      b(); // 100% transparent dynamic dispatch
 }

 Unfortunately, this is what DMD had to say about this:

 C:\Users\g.gyolchanyan\Desktop\test.d(3): Error: found 'This_' when
 expecting ')'
 C:\Users\g.gyolchanyan\Desktop\test.d(3): Error: semicolon expected
 following function declaration
 C:\Users\g.gyolchanyan\Desktop\test.d(3): Error: Declaration expected,
 not ')'

 It looks like DMD thinks I was gonna write a postblit constructor and I
 guess the functionality is already there, but can't be reached due to a
 parsing error.

I haven't even thought about this use case. It would be so cool. -- /Jacob Carlborg
Feb 20 2013
parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
On Wed, Feb 20, 2013 at 6:42 PM, Jacob Carlborg <doob me.com> wrote:

 On 2013-02-20 15:37, Gor Gyolchanyan wrote:

  After I tested this, immediately thought of the constructor. The
 constructor of the base class is guaranteed to be called when
 constructing a derived class, right? Even if the call is implicit, it
 still happens and at the call site the concrete type being constructed
 is known, so in theory, a template this parameter on the base class's
 constructor should allow the base class to know the static type of the
 object being constructed (which is immensely useful for implementing
 dynamic dispatch classes).

 class Base
 {
      this(this This_)()
      {
          // Build a dispatch table using __traits(allMethods, This_)
      }

      void opCall(Payload_)(Payload_ payload_)
      {
          // Dynamically dispatch payload_ using the previously built
 dispatch table.
      }
 }

 class Derived: Base
 {
      // implicitly generated constructor will call the Base.this() and
 implicitly give it the static type of Derived.
 }

 unittest
 {
      Base b = new Derived;
      b(); // 100% transparent dynamic dispatch
 }

 Unfortunately, this is what DMD had to say about this:

 C:\Users\g.gyolchanyan\**Desktop\test.d(3): Error: found 'This_' when
 expecting ')'
 C:\Users\g.gyolchanyan\**Desktop\test.d(3): Error: semicolon expected
 following function declaration
 C:\Users\g.gyolchanyan\**Desktop\test.d(3): Error: Declaration expected,
 not ')'

 It looks like DMD thinks I was gonna write a postblit constructor and I
 guess the functionality is already there, but can't be reached due to a
 parsing error.

I haven't even thought about this use case. It would be so cool. -- /Jacob Carlborg

This would mean, that D can flawlessly mix together static and dynamic typing to achieve maximum flexibility (using dynamic typing like this) and maximum performance (using static typing when this isn't required). No statically-typed and no dynamically-typed language can combine flexibility and performance right now. Combined with the upcoming revamp of D's compile-time and (built on top of it) run-time reflection, this will make D the ultimate modeling tool for building systems of arbitrary dynamicity and maximum performance. By the way, what's up with the new reflection thing that Andrei once wrote about? -- Bye, Gor Gyolchanyan.
Feb 20 2013
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/20/2013 03:37 PM, Gor Gyolchanyan wrote:
 ...

 Is there any change of this being fixed any time soon?
 ...

According to the online documentation it seems like it should work: http://dlang.org/template.html#TemplateThisParameter states: "TemplateThisParameters are used in member function templates to pick up the type of the this reference." http://dlang.org/class.html states: Classes consist of: ... * member functions ... * Constructors I guess just post it to bugzilla.
Feb 20 2013
next sibling parent reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
On Wed, Feb 20, 2013 at 7:29 PM, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 02/20/2013 03:37 PM, Gor Gyolchanyan wrote:

 ...


 Is there any change of this being fixed any time soon?
 ...

According to the online documentation it seems like it should work: http://dlang.org/template.**html#TemplateThisParameter<http://dlang.org/template.html#TemplateThisParameter>states: "TemplateThisParameters are used in member function templates to pick up the type of the this reference." http://dlang.org/class.html states: Classes consist of: ... * member functions ... * Constructors I guess just post it to bugzilla.

http://d.puremagic.com/issues/show_bug.cgi?id=9551 I really really hope this gets fixed soon, because my project is stuck because of this. -- Bye, Gor Gyolchanyan.
Feb 20 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-02-20 16:38, Gor Gyolchanyan wrote:

 http://d.puremagic.com/issues/show_bug.cgi?id=9551

 I really really hope this gets fixed soon, because my project is stuck
 because of this.

You can't pass the static type to the base class, just as a workaround? class Base (T) { } class Sub : Base!(Sub) { } -- /Jacob Carlborg
Feb 20 2013
parent reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
This adds boilerplate, that I can't afford. I need to transparently add
dynamic dispatch to classes and I can't modify all of them. Besides, I have
had experience with this previously and it causes a ton of problems,
because there's no way of making sure the static type is passed and its'
the right one.


On Wed, Feb 20, 2013 at 7:46 PM, Jacob Carlborg <doob me.com> wrote:

 On 2013-02-20 16:38, Gor Gyolchanyan wrote:

  http://d.puremagic.com/issues/**show_bug.cgi?id=9551<http://d.puremagic.com/issues/show_bug.cgi?id=9551>
 I really really hope this gets fixed soon, because my project is stuck
 because of this.

You can't pass the static type to the base class, just as a workaround? class Base (T) { } class Sub : Base!(Sub) { } -- /Jacob Carlborg

-- Bye, Gor Gyolchanyan.
Feb 20 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-02-20 16:56, Gor Gyolchanyan wrote:
 This adds boilerplate, that I can't afford. I need to transparently add
 dynamic dispatch to classes and I can't modify all of them. Besides, I
 have had experience with this previously and it causes a ton of
 problems, because there's no way of making sure the static type is
 passed and its' the right one.

The compiler will make sure the a type is passed. You could add some constraints on the template type but it wouldn't be 100% bulletproof. class Base (T : Base) { } class Sub : Base!(Sub) { } -- /Jacob Carlborg
Feb 20 2013
prev sibling parent kenji hara <k.hara.pg gmail.com> writes:
Constructor should check its qualifier as a switch to select construction
strategy. It is described in TDPL, but it has not been yet implemented.

The combination of constructor and TemplateThisParameter would affect to
that not-implemented feature. As a conclusion, its semantics is YET NOT
DEFINED.

(Similar thing exists with "inout constructor". It is not also yet defined.)

Kenji Hara

2013/2/21 Gor Gyolchanyan <gor.f.gyolchanyan gmail.com>

 On Wed, Feb 20, 2013 at 7:29 PM, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 02/20/2013 03:37 PM, Gor Gyolchanyan wrote:

 ...


 Is there any change of this being fixed any time soon?
 ...

According to the online documentation it seems like it should work: http://dlang.org/template.**html#TemplateThisParameter<http://dlang.org/template.html#TemplateThisParameter>states: "TemplateThisParameters are used in member function templates to pick up the type of the this reference." http://dlang.org/class.html states: Classes consist of: ... * member functions ... * Constructors I guess just post it to bugzilla.

http://d.puremagic.com/issues/show_bug.cgi?id=9551 I really really hope this gets fixed soon, because my project is stuck because of this. -- Bye, Gor Gyolchanyan.

Feb 20 2013
prev sibling parent "Igor Stepanov" <wazar.leollone yahoo.com> writes:
What about template this for compile-time constructing of structs 
(classes?)?
e.g.
struct BigDecimal
{
   this(string arg)
   {
     *this = str2Dec(arg);
   }
   template this(string arg)
   {
     enum this = str2Dec(arg);
   }

   static BigDecimal str2Dec(string arg) //can be evaluated at 
compile time
   {
     //...
   }
}

void main()
{
   string str = "42.24";
   BigDecimal num1 = str;//Calling constructor BigDecimal.this
   BigDecimal num2 = "3,1415926535 8979323846 2643383279 
5028841971 6939937510 5820974944 5923078164 0628620899 8628034825 
3421170679 8214808651 3282306647 0938446095 5058223172 5359408128 
4811174502 8410270193 8521105559 6446229489 5493038196 4428810975 
6659334461 2847564823 3786783165 2712019091 4564856692 3460348610 
4543266482 1339360726 0249141273 7245870066 0631558817 4881520920 
9628292540 9171536436 7892590360 0113305305 4882046652 1384146951 
9415116094 3305727036 5759591953 0921861173 8193261179"; 
//Calling template this at compile time.
}
Feb 20 2013