www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Re: inheriting ctors?

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
There is an AutoImplement class template in
http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#AutoImplement , which
I've just been trying out. Apparently you can pass it 1: a Base class, 2: a
templated function to filter out which functions you want to inherit/overwrite
from the Base class, and 3: a template function which can re-write the bodies
of each function which is not filtered out (+ there are some "macros" which you
can use to quickly access the functions' parameters and other such things).

But it's a mess to work with, and I'm not sure how I'm supossed to use it if
I'm trying to do something like "class B : A".., because it looks like
AutoImplement creates a class and instantiates it, it doesn't return a string
ready to be mixed in like you are doing in your example.

There's an example of BlackBox and WhiteBox, which use AutoImplement, on the
same page. Maybe you guys could make sense of it, it's too hard for me atm. (D
newbie)

// Offtopic
Template errors are so hard to grasp, most of the time it's best to just ignore
them and take some logical steps to fix the errors. At least that's in my case
true..

Rory Mcguire Wrote:

 Rory Mcguire wrote:
 
 Philippe Sigaud wrote:
 
 On Fri, Aug 6, 2010 at 11:43, Rory Mcguire <rjmcguire gm_no_ail.com>
 wrote:
 
 
 I've been trying to make a template for this but it seems that dmd still
 won't allow me to get the parameters of the constructors. dmd Seems to
 think
 that I'm trying to use it as a property.

 void main() {
    foreach (m; __traits(getOverloads, A, "__ctor")) {
        pragma(msg, m.stringof); // it thinks I'm calling m
    }
 }

 constructors.d(34): Error: constructor constructors.A.this (int x) is
 not callable using argument types ()

This is my new once-a-day bug :( Using a function alias, and being unable to call properties on it, because DMD thinks I'm calling it. Man, it's no property, just a name! Anyway, just pragma(msg, m) works, strangely. I think I found a way to use m, somewhat: void main() { foreach (m; __traits(getOverloads, A, "__ctor")) { pragma(msg, m); // it thinks I'm calling m typeof(&m) tmp = &m; writeln( (ParameterTypeTuple!tmp).stringof); // (int), (double), (string) writeln( (ParameterTypeTuple!m).stringof); // (int), (int), (int) writeln( typeof(&m).stringof); // A function(int x), A function(double x), A function(string s) } } using ParameterTypeTuple!m directly does not differentiate the m's. But using a temporary pointer, it seems to work. Oh and I even get the arguments names ! Philippe

Thanks!! works now. Now we just need to be able to select which constructors we actually want. string inheritconstructors_helper(alias T)() { string s; foreach (m; __traits(getOverloads, T, "__ctor")) { string args, args1; foreach (i, cons; ParameterTypeTuple!(typeof(&m))) { pragma(msg, cons.stringof); args ~= ","~cons.stringof~" v"~to!string(i); args1 ~= ",v"~to!string(i); } args = args.length < 1 ? args : args[1..$]; args1 = args1.length < 1 ? args1 : args1[1..$]; s ~= "this("~args~") { super("~args1~"); }\n"; } return s; } class A { int i; //private this() {} this(int x) { i = x; } this(float x) { i = cast(int)x; // ignore bad code } this(string s, int mul) { // test multiple args i = to!int(s) * mul; } } class B : A { mixin(inheritconstructors_helper!A()); // InheritConstructors!A; } void main() { A a = new B(4); a = new B("42", 2); }

Got selection working: string inheritconstructors_helper(alias T,Selectors...)() { string s; foreach (m; __traits(getOverloads, T, "__ctor")) { string args, args1; pragma(msg, typeof(&m)); /*foreach (sel; Selectors) { pragma(msg, sel, is (sel == typeof(&m))); continue top; }*/ if (staticIndexOf!(typeof(&m), Selectors)==-1) { continue; } foreach (i, cons; ParameterTypeTuple!(typeof(&m))) { pragma(msg, cons.stringof); args ~= ","~cons.stringof~" v"~to!string(i); args1 ~= ",v"~to!string(i); } args = args.length < 1 ? args : args[1..$]; args1 = args1.length < 1 ? args1 : args1[1..$]; s ~= "this("~args~") { super("~args1~"); }\n"; } return s; } Usage: class B : A { mixin(inheritconstructors_helper!(A,TypeTuple!(A function(string,int) ,A function(int)))()); }

Aug 06 2010
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Here's an example:

import std.stdio;
import std.traits;
import std.conv;
import std.typecons;

class C
{
    int m_value;
    
    int testMe()
    {
        return 1;
    }
    
    this(int x) 
    { 
        m_value = x; 
    }
    
    this(int x, int z)
    {
        m_value = x + z;
    }
}

template inheritClassMethods(Base)
{
    alias AutoImplement!(Base, generateEmptyFunction, isAbstractFunction)
inheritClassMethods;
}

void main()
{
    auto c = new inheritClassMethods!C(42, 56);
} 

So basically you can instantiate a highly modified class that's based on
another class at compile time. You can change the method definitions, and even
leave some out. What's really cool about this is that you can, say, add logging
ability to all methods of a class without having to manually add them in class
definition (there's an example in the docs). Which could be quite useful in
debugging I suposse.

isAbstractFunction and generateEmptyFunction are from std.typecons (I think),
but you can pass your own template functions instead of these.

I'm just getting a lot of errors because it seems very sensitive to what kind
of functions you're going to inherit.. well it's complicated. And there's some
warnings about bugs in the sources. Still, I like the premise of AutoImplement.

Andrej Mitrovic Wrote:

 There is an AutoImplement class template in
http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#AutoImplement , which
I've just been trying out. Apparently you can pass it 1: a Base class, 2: a
templated function to filter out which functions you want to inherit/overwrite
from the Base class, and 3: a template function which can re-write the bodies
of each function which is not filtered out (+ there are some "macros" which you
can use to quickly access the functions' parameters and other such things).
 
 But it's a mess to work with, and I'm not sure how I'm supossed to use it if
I'm trying to do something like "class B : A".., because it looks like
AutoImplement creates a class and instantiates it, it doesn't return a string
ready to be mixed in like you are doing in your example.
 
 There's an example of BlackBox and WhiteBox, which use AutoImplement, on the
same page. Maybe you guys could make sense of it, it's too hard for me atm. (D
newbie)
 
 // Offtopic
 Template errors are so hard to grasp, most of the time it's best to just
ignore them and take some logical steps to fix the errors. At least that's in
my case true..
 
 Rory Mcguire Wrote:
 
 Rory Mcguire wrote:
 
 Philippe Sigaud wrote:
 
 On Fri, Aug 6, 2010 at 11:43, Rory Mcguire <rjmcguire gm_no_ail.com>
 wrote:
 
 
 I've been trying to make a template for this but it seems that dmd still
 won't allow me to get the parameters of the constructors. dmd Seems to
 think
 that I'm trying to use it as a property.

 void main() {
    foreach (m; __traits(getOverloads, A, "__ctor")) {
        pragma(msg, m.stringof); // it thinks I'm calling m
    }
 }

 constructors.d(34): Error: constructor constructors.A.this (int x) is
 not callable using argument types ()

This is my new once-a-day bug :( Using a function alias, and being unable to call properties on it, because DMD thinks I'm calling it. Man, it's no property, just a name! Anyway, just pragma(msg, m) works, strangely. I think I found a way to use m, somewhat: void main() { foreach (m; __traits(getOverloads, A, "__ctor")) { pragma(msg, m); // it thinks I'm calling m typeof(&m) tmp = &m; writeln( (ParameterTypeTuple!tmp).stringof); // (int), (double), (string) writeln( (ParameterTypeTuple!m).stringof); // (int), (int), (int) writeln( typeof(&m).stringof); // A function(int x), A function(double x), A function(string s) } } using ParameterTypeTuple!m directly does not differentiate the m's. But using a temporary pointer, it seems to work. Oh and I even get the arguments names ! Philippe

Thanks!! works now. Now we just need to be able to select which constructors we actually want. string inheritconstructors_helper(alias T)() { string s; foreach (m; __traits(getOverloads, T, "__ctor")) { string args, args1; foreach (i, cons; ParameterTypeTuple!(typeof(&m))) { pragma(msg, cons.stringof); args ~= ","~cons.stringof~" v"~to!string(i); args1 ~= ",v"~to!string(i); } args = args.length < 1 ? args : args[1..$]; args1 = args1.length < 1 ? args1 : args1[1..$]; s ~= "this("~args~") { super("~args1~"); }\n"; } return s; } class A { int i; //private this() {} this(int x) { i = x; } this(float x) { i = cast(int)x; // ignore bad code } this(string s, int mul) { // test multiple args i = to!int(s) * mul; } } class B : A { mixin(inheritconstructors_helper!A()); // InheritConstructors!A; } void main() { A a = new B(4); a = new B("42", 2); }

Got selection working: string inheritconstructors_helper(alias T,Selectors...)() { string s; foreach (m; __traits(getOverloads, T, "__ctor")) { string args, args1; pragma(msg, typeof(&m)); /*foreach (sel; Selectors) { pragma(msg, sel, is (sel == typeof(&m))); continue top; }*/ if (staticIndexOf!(typeof(&m), Selectors)==-1) { continue; } foreach (i, cons; ParameterTypeTuple!(typeof(&m))) { pragma(msg, cons.stringof); args ~= ","~cons.stringof~" v"~to!string(i); args1 ~= ",v"~to!string(i); } args = args.length < 1 ? args : args[1..$]; args1 = args1.length < 1 ? args1 : args1[1..$]; s ~= "this("~args~") { super("~args1~"); }\n"; } return s; } Usage: class B : A { mixin(inheritconstructors_helper!(A,TypeTuple!(A function(string,int) ,A function(int)))()); }


Aug 06 2010
next sibling parent Rory Mcguire <rjmcguire gm_no_ail.com> writes:
I had been trying to use AutoImplement to make something before but it gave 
me weird errors.
I'm going to try using it for implementing "this" when I get some time.

Andrej Mitrovic wrote:

 Here's an example:

Aug 09 2010
prev sibling parent Rory Mcguire <rjmcguire gm_no_ail.com> writes:
Thanks for suggestion

Andrej Mitrovic wrote:

 Here's an example:

Aug 09 2010
prev sibling parent div0 <div0 sourceforge.net> writes:
On 06/08/2010 22:57, Andrej Mitrovic wrote:

 // Offtopic Template errors are so hard to grasp, most of the time
 it's best to just ignore them and take some logical steps to fix the
 errors. At least that's in my case true..

lol, that's true. I've been basing out c++ & d template code for years and that's pretty much what I do. Unless the template author has specifically added static asserts to catch an obvious error, most template error messages are useless garbage. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Aug 07 2010