www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting the parameters of a struct/class constructor

reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
Hello all,

Is there a way to construct a tuple of the types that need to be passed to a 
struct or class's constructor?

I tried using ParameterTypeTuple either on the class or its constructor:

     ParameterTypeTuple!A

or

     ParameterTypeTuple!(A.this)

... but neither works: the former generates an error,

     Error: template instance ParameterTypeTuple!(A) ParameterTypeTuple!(A)
does 
not match template declaration ParameterTypeTuple(func...) if (func.length == 1 
&& isCallable!(func))

while the latter generates,

     Error: identifier expected following '.', not 'this'

A (broken) bit of sample code is attached which illustrates what I'm trying to 
achieve.  Can anyone advise?

Thanks & best wishes,

      -- Joe
Jan 24 2013
next sibling parent "Rob T" <alanb ucora.com> writes:
There may be more than one "this", so you'll have to specify the 
args for each specific constructor manually.

Disclaimer: Someone else may have a better solution as I'm not 
that much of an expert in this area.

This sample may point you in the right direction ...

import std.typetuple;

struct X
{
     alias TypeTuple!(int, double) CONSTUCT1;
     alias TypeTuple!(int, double, string) CONSTUCT2;

     this( CONSTUCT1 args )
     {
         alias args[0] a_int;
         alias args[0] a_double;

         _a = a_int;
         _b = b_double;

     }

     this( CONSTUCT2[0] a_int, CONSTUCT2[1] b_double, CONSTUCT2[2] 
c_string  )
     {

         _a = a_int;
         _b = b_double;
         writeln(c_string);
     }

     int _a;
     double _b;

}


void foo(X.CONSTUCT1[0] a, X.CONSTUCT1[1] b )
{

   ...

}

void bar(X.CONSTUCT2 args )
{

    alias args[0] a_int;
    alias args[1] a_double;
    alias args[2] a_string;
   ...

}

Hope this helps.

--rt
Jan 24 2013
prev sibling parent reply "mist" <none none.none> writes:
You can use "magic" functions __ctor and __dtor which actually 
serve as constructor and destructor implementations behind the 
scene.

Example and proof-of-concept: http://dpaste.1azy.net/fd924332

Have no idea if it is explicitly defined by spec somewhere though.
Jan 24 2013
parent reply "Rob T" <alanb ucora.com> writes:
On Thursday, 24 January 2013 at 18:41:31 UTC, mist wrote:
 You can use "magic" functions __ctor and __dtor which actually 
 serve as constructor and destructor implementations behind the 
 scene.

 Example and proof-of-concept: http://dpaste.1azy.net/fd924332

 Have no idea if it is explicitly defined by spec somewhere 
 though.
If you have more than one ctor it seems to take the first one http://dpaste.1azy.net/b994fdf3 I don't know if you will able to rely on the order unless it's a part of the spec. --rt
Jan 24 2013
next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Thu, Jan 24, 2013 at 10:34 PM, Rob T <alanb ucora.com> wrote:
 On Thursday, 24 January 2013 at 18:41:31 UTC, mist wrote:
 You can use "magic" functions __ctor and __dtor which actually serve as
 constructor and destructor implementations behind the scene.

 Example and proof-of-concept: http://dpaste.1azy.net/fd924332

 Have no idea if it is explicitly defined by spec somewhere though.
If you have more than one ctor it seems to take the first one http://dpaste.1azy.net/b994fdf3 I don't know if you will able to rely on the order unless it's a part of the spec.
IIRC, you can use __traits(getOverloads, mytype.__ctor) to get all constructor overloads. See: http://dlang.org/traits.html#getOverloads I used this in conjunction with __traits(getMember, ...) to get the entire list of member, overloads included.
Jan 24 2013
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/24/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 IIRC, you can use __traits(getOverloads, mytype.__ctor) to get all
 constructor overloads.
 See:
 http://dlang.org/traits.html#getOverloads

 I used this in conjunction with __traits(getMember, ...) to get the
 entire list of member, overloads included.
I don't understand why, but it seems DForum doesn't show up any of my posts. I've posted this as my second reply (hope this makes it): If you have multiple constructors you can pick the parameters with a helper template: import std.traits, std.string; struct A { this(int a, double b) { } this(float y) { } } template PickCtorParams(Type, size_t index) { enum ctorLen = __traits(getOverloads, Type, "__ctor").length; static if (index < ctorLen) { alias ParameterTypeTuple!(__traits(getOverloads, A, "__ctor")[index]) PickCtorParams; } else { static assert(0, format("index %s exceeds %s ctors for type %s", index, ctorLen, Type.stringof)); } } void main() { pragma(msg, PickCtorParams!(A, 0)); // (int, double) pragma(msg, PickCtorParams!(A, 1)); // (float) pragma(msg, PickCtorParams!(A, 2)); // out of bounds }
Jan 24 2013
parent "Rob T" <alanb ucora.com> writes:
On Thursday, 24 January 2013 at 22:49:33 UTC, Andrej Mitrovic 
wrote:
 On 1/24/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 IIRC, you can use __traits(getOverloads, mytype.__ctor) to get 
 all
 constructor overloads.
 See:
 http://dlang.org/traits.html#getOverloads

 I used this in conjunction with __traits(getMember, ...) to 
 get the
 entire list of member, overloads included.
I don't understand why, but it seems DForum doesn't show up any of my posts. I've posted this as my second reply (hope this makes it):
The thread got split up into two separate threads. Your missing post shows up in the split. I really hate it when it does this. --rt
Jan 24 2013