Thread overview
How to chain constructor args to a template memeber
Mar 11, 2010
BCS
Mar 11, 2010
Jacob Carlborg
Mar 11, 2010
Lutger
Mar 11, 2010
BCS
Mar 11, 2010
BCS
Mar 11, 2010
Philippe Sigaud
March 11, 2010
Using D2, I have a template class that looks something like this:

class C(T) { T t; }

(For simplicity, assume T is required to be a struct of some kind.) I want to have a constructor that passes on some of it's args to a constructor for t. This is easy as long as I don't need it to work for arbitrary constructors.

What I want to do (that doesn't seem to work) is this:

this(Args...)(int foo, float bar, Args args)
{
  t = T(args);

  ...
}

Any ideas on fixes or work arounds?

-- 
... <IXOYE><



March 11, 2010
On 3/11/10 08:58, BCS wrote:
> Using D2, I have a template class that looks something like this:
>
> class C(T) { T t; }
>
> (For simplicity, assume T is required to be a struct of some kind.) I
> want to have a constructor that passes on some of it's args to a
> constructor for t. This is easy as long as I don't need it to work for
> arbitrary constructors.
>
> What I want to do (that doesn't seem to work) is this:
>
> this(Args...)(int foo, float bar, Args args)
> {
> t = T(args);
>
> ...
> }
>
> Any ideas on fixes or work arounds?
>

D doesn't seem support constructor templates in classes.

March 11, 2010
BCS wrote:

> Using D2, I have a template class that looks something like this:
> 
> class C(T) { T t; }
> 
> (For simplicity, assume T is required to be a struct of some kind.) I want to have a constructor that passes on some of it's args to a constructor for t. This is easy as long as I don't need it to work for arbitrary constructors.
> 
> What I want to do (that doesn't seem to work) is this:
> 
> this(Args...)(int foo, float bar, Args args)
> {
>    t = T(args);
> 
>    ...
> }
> 
> Any ideas on fixes or work arounds?
> 

Workaround if T has a single constructor, perhaps it can be generalized with some work:

this(int foo, float bar, std.traits.ParameterTypeTuple!(T.__ctor) args)
{
    t = T(args);
}
March 11, 2010
On Thu, 11 Mar 2010 02:58:52 -0500, BCS <none@anon.com> wrote:

> Using D2, I have a template class that looks something like this:
>
> class C(T) { T t; }
>
> (For simplicity, assume T is required to be a struct of some kind.) I want to have a constructor that passes on some of it's args to a constructor for t. This is easy as long as I don't need it to work for arbitrary constructors.
>
> What I want to do (that doesn't seem to work) is this:
>
> this(Args...)(int foo, float bar, Args args)
> {
>    t = T(args);
>
>    ...
> }
>
> Any ideas on fixes or work arounds?

What about a static function instead of a constructor?

i.e.

static C create(Args...)(int foo, float bar, Args args)
{
   auto c = new C(foo, bar);
   c.t = T(args);
   return c;
}

It's a shame template constructors aren't allowed, they aren't even virtual functions!

-Steve
March 11, 2010
Hello Lutger,

> Workaround if T has a single constructor, perhaps it can be
> generalized with some work:
> 
> this(int foo, float bar, std.traits.ParameterTypeTuple!(T.__ctor)
> args)
> {
> t = T(args);
> }

Not exactly ideal, but... :)


-- 
... <IXOYE><



March 11, 2010
Hello Steven,

> What about a static function instead of a constructor?
> 
> i.e.
> 
> static C create(Args...)(int foo, float bar, Args args)
> {
> auto c = new C(foo, bar);
> c.t = T(args);
> return c;
> }

That's my fallback position.

> It's a shame template constructors aren't allowed, they aren't even
> virtual functions!

Ditto.

-- 
... <IXOYE><



March 11, 2010
On Thu, Mar 11, 2010 at 21:03, BCS <none@anon.com> wrote:

>
>
>> i.e.
>>
>> static C create(Args...)(int foo, float bar, Args args)
>> {
>> auto c = new C(foo, bar);
>> c.t = T(args);
>> return c;
>> }
>>
>
> What about a static function instead of a constructor?
>

Two variations on the same theme:

storing (Args...) as a template parameter in the host class

class Host(Hosted, Args...) {
    Hosted t;
    this(int foo, float bar, Args args)
    {
     t = Hosted(args);
    }
}

and using a helper function to do the type extraction:

Host!(Hosted, Args) host(Hosted, Args...)(int foo, float bar, Args args)
{
    return new Host!(Hosted, Args)(foo, bar, args);
}

Or, give the host a constructor taking a Hosted already created:


class Host2(Hosted) {
    Hosted h;
    this(int foo, float bar, Hosted h)
    {
        this.h = h;
    }
}

Host2!(Hosted) host2(Hosted, Args...)(int foo, float bar, Args args)
{
    auto h = Hosted(args);
    return new Host2!(Hosted)(foo, bar, h);
}

Usage:

struct OneArg { char c;}

struct ManyArgs { int i; float f;}

void main()
{
    auto c0 = host!ManyArgs(1,2.0,3,4.0);
    auto c1 = host!OneArg(1,2.0,'c');
    auto c2 = host2!ManyArgs(1,2.0,3,4.0);
 }