Thread overview
Re: Extracting template parameters
Nov 06, 2012
Tobias Pankrath
Nov 06, 2012
Simen Kjaeraas
Nov 06, 2012
H. S. Teoh
Nov 06, 2012
Andrej Mitrovic
November 06, 2012
On 11/06/2012 04:20 PM, Joseph Rushton Wakeling wrote:
> The use-case I'm thinking of is a function something like this (somewhat
> pseudo-code-y):
>
>      auto fooToBar(FooInstance f)
>      {
>          Bar!(f.T1, f.T2, f.T3) b;
>          // set values etc.
>          return b;
>      }
>
> Of course the f.T1 notation is my fiction, but it gives the idea of what is
> needed -- is there a means to extract and use template parameters in this way? I
> assume something from std.traits but it's not entirely clear what or how ...

Ideally this solution would work for non-identical lists of template parameters.  E.g. for

    Foo(T1, T2, T3, T4)
    {
    }

    Bar(X1, X2)
    {
    }

I'd like to be able to instantiate something like: Bar!(f.T2, f.T4) [again, using my fictional notation].
November 06, 2012
On 11/06/2012 04:25 PM, Joseph Rushton Wakeling wrote:
Look at the is() expression in the language spec.

I didn't get it to work with a template constraint, because the pattern matched parameter are out of scope in the function body.

----
struct A(T1, T2)
{
}

struct B(B1, B2) {}


void foo(T)(T x)
{
    static if(is(T Dummy : A!(P), P...))
    {
        pragma(msg, P);
    }
}

void main() {
    A!(int, float) a;
    foo(a);
}

November 06, 2012
On 2012-11-06, 16:20, Joseph Rushton Wakeling wrote:

> Suppose that I have two struct templates which take identical parameter lists:
>
>      struct Foo(T1, T2, T3)
>      {
>          ...
>      }
>
>      struct Bar(T1, T2, T3)
>      {
>          ...
>      }
>
> Now suppose that I have a Foo which has been instantiated with a given set of parameters.  Is there any way for me to say, "now instantiate a Bar with the same parameters?"
>
> The use-case I'm thinking of is a function something like this (somewhat pseudo-code-y):
>
>      auto fooToBar(FooInstance f)
>      {
>          Bar!(f.T1, f.T2, f.T3) b;
>          // set values etc.
>          return b;
>      }
>
> Of course the f.T1 notation is my fiction, but it gives the idea of what is needed -- is there a means to extract and use template parameters in this way? I assume something from std.traits but it's not entirely clear what or how ...

In addition to Dan's answer, let me present a general solution:

template InstantiationInfo( T ) {
    static if ( is( T t == U!V, alias U, V... ) ) {
        alias U Template;
        alias V Parameters;
    } else {
        static assert(false, T.stringof ~ " is not a template type instantiation.");
    }
}

With this, you can extract the parameters to a template
(InstantiationInfo!Foo.Parameters) or the template used
(InstantiationInfo!Foo.Template).

-- 
Simen
November 06, 2012
On Tue, Nov 06, 2012 at 04:20:34PM +0100, Joseph Rushton Wakeling wrote:
> Suppose that I have two struct templates which take identical parameter lists:
> 
>     struct Foo(T1, T2, T3)
>     {
>         ...
>     }
> 
>     struct Bar(T1, T2, T3)
>     {
>         ...
>     }
> 
> Now suppose that I have a Foo which has been instantiated with a given set of parameters.  Is there any way for me to say, "now instantiate a Bar with the same parameters?"

You could alias the parameters so that they're accessible from outside:

	struct Foo(T1, T2, T3)
	{
		alias T1 t1;
		alias T2 t2;
		alias T3 t3;
		...
	}

	struct Bar(X1, X2)
	{
		...
	}

	auto fooToBar(FooInstance)(FooInstance f)
	{
		return Bar!(f.t2, f.t3)();
	}

This works if T1, T2, T3 are types. If they're values, you'll need to use enums in Foo instead.


T

-- 
There are three kinds of people in the world: those who can count, and those who can't.
November 06, 2012
On 11/6/12, Simen Kjaeraas <simen.kjaras@gmail.com> wrote:
> In addition to Dan's answer, let me present a general solution:
>
> template InstantiationInfo( T ) {
>      static if ( is( T t == U!V, alias U, V... ) ) {
>          alias U Template;
>          alias V Parameters;
>      } else {
>          static assert(false, T.stringof ~ " is not a template type
> instantiation.");
>      }
> }

I think Kenji fixed this recently because it didn't work several releases ago. You can now do cool things with template constraints. For example if you want to limit a template to only allow types that are instances of a specific template you can do:

struct Foo(T...) { }

struct Bar(T)
    if (is(T x == Foo!X, X...))  // T must be a Foo instance
{
}

struct Other(T...) { }

void main()
{
    alias Bar!(Foo!int) A;  // ok
    alias Bar!(Other!int) B;  // fail
}