www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template type deduction

reply "Phil Lavoie" <maidenphil hotmail.com> writes:
Imagine you have something like this:

struct MyParamType( T1, T2 ) { ... }

and then a compound:

struct MyCoumpound( T ) if( isMyParamType!T ) { ... }

template isMyParamType( T ) {
   enum isMyParamType = ... //Complete this
}

Is it possible to deduce that T is a parameterized struct using 
isExpressions:

enum isMyParamType = is( T U: MyParamType!U ); //Works for 1 
parameter, but what do you do when you have plenty?

Thanks!
Phil
Jan 20 2013
next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Jan 20, 2013 at 3:59 PM, Phil Lavoie <maidenphil hotmail.com> wrote:
 Imagine you have something like this:

 struct MyParamType( T1, T2 ) { ... }

 and then a compound:

 struct MyCoumpound( T ) if( isMyParamType!T ) { ... }

 template isMyParamType( T ) {
   enum isMyParamType = ... //Complete this
 }

 Is it possible to deduce that T is a parameterized struct using
 isExpressions:

 enum isMyParamType = is( T U: MyParamType!U ); //Works for 1 parameter, but
 what do you do when you have plenty?
This should work: is(T _ : MyParamType!U, U...) ( '_' just to tell someone reading the code this part is not used)
Jan 20 2013
next sibling parent "Phil Lavoie" <maidenphil hotmail.com> writes:
On Sunday, 20 January 2013 at 15:39:53 UTC, Philippe Sigaud wrote:
 On Sun, Jan 20, 2013 at 3:59 PM, Phil Lavoie 
 <maidenphil hotmail.com> wrote:
 Imagine you have something like this:

 struct MyParamType( T1, T2 ) { ... }

 and then a compound:

 struct MyCoumpound( T ) if( isMyParamType!T ) { ... }

 template isMyParamType( T ) {
   enum isMyParamType = ... //Complete this
 }

 Is it possible to deduce that T is a parameterized struct using
 isExpressions:

 enum isMyParamType = is( T U: MyParamType!U ); //Works for 1 
 parameter, but
 what do you do when you have plenty?
This should work: is(T _ : MyParamType!U, U...) ( '_' just to tell someone reading the code this part is not used)
And it does buddy, thanks!
Jan 20 2013
prev sibling parent reply "Phil Lavoie" <maidenphil hotmail.com> writes:
On Sunday, 20 January 2013 at 15:39:53 UTC, Philippe Sigaud wrote:
 On Sun, Jan 20, 2013 at 3:59 PM, Phil Lavoie 
 <maidenphil hotmail.com> wrote:
 Imagine you have something like this:

 struct MyParamType( T1, T2 ) { ... }

 and then a compound:

 struct MyCoumpound( T ) if( isMyParamType!T ) { ... }

 template isMyParamType( T ) {
   enum isMyParamType = ... //Complete this
 }

 Is it possible to deduce that T is a parameterized struct using
 isExpressions:

 enum isMyParamType = is( T U: MyParamType!U ); //Works for 1 
 parameter, but
 what do you do when you have plenty?
This should work: is(T _ : MyParamType!U, U...) ( '_' just to tell someone reading the code this part is not used)
Is there also a way to extract per parameter information (ex: type) using type deduction. Let me illustrate: struct Toto( T1, T2 ) { alias Key = T1; alias Value = T2; } struct OuterToto( T ) if( isToto!T ) { T.Key key; T.Value value; } Imagine I would want that but without using inner aliases, is this possible? Thanks! Phil
Jan 20 2013
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Jan 20, 2013 at 5:01 PM, Phil Lavoie <maidenphil hotmail.com> wrote:

 Is there also a way to extract per parameter information (ex: type) using
 type deduction. Let me illustrate:

 struct Toto( T1, T2 ) {
  alias Key = T1;
  alias Value = T2;
 }

 struct OuterToto( T ) if( isToto!T ) {
   T.Key key;
   T.Value value;
 }

 Imagine I would want that but without using inner aliases, is this possible?
Sure, the U... part is accessible inside the static if. Just define a generic helper template: struct Toto(First, Second) { } template TemplateArguments(T) { static if (is(T _ : a!(Args), alias a, Args...)) alias TemplateArguments = Args; else alias TemplateArguments = void; } template TemplateName(T) { static if (is(T _ : a!(Args), alias a, Args...)) alias TemplateName = a; else alias TemplateName = void; } void main(string[] args) { alias Type = Toto!(int, double); writeln(TemplateArguments!(Type).stringof); writeln(TemplateName!(Type).stringof); alias T = TemplateName!(Type); alias Swapped = T!(double, int); // And you can use T as a template. } As you can see, you can even use the deduced template name.
Jan 20 2013
parent "Phil Lavoie" <maidenphil hotmail.com> writes:
On Sunday, 20 January 2013 at 16:11:08 UTC, Philippe Sigaud wrote:
 On Sun, Jan 20, 2013 at 5:01 PM, Phil Lavoie 
 <maidenphil hotmail.com> wrote:

 Is there also a way to extract per parameter information (ex: 
 type) using
 type deduction. Let me illustrate:

 struct Toto( T1, T2 ) {
  alias Key = T1;
  alias Value = T2;
 }

 struct OuterToto( T ) if( isToto!T ) {
   T.Key key;
   T.Value value;
 }

 Imagine I would want that but without using inner aliases, is 
 this possible?
Sure, the U... part is accessible inside the static if. Just define a generic helper template: struct Toto(First, Second) { } template TemplateArguments(T) { static if (is(T _ : a!(Args), alias a, Args...)) alias TemplateArguments = Args; else alias TemplateArguments = void; } template TemplateName(T) { static if (is(T _ : a!(Args), alias a, Args...)) alias TemplateName = a; else alias TemplateName = void; } void main(string[] args) { alias Type = Toto!(int, double); writeln(TemplateArguments!(Type).stringof); writeln(TemplateName!(Type).stringof); alias T = TemplateName!(Type); alias Swapped = T!(double, int); // And you can use T as a template. } As you can see, you can even use the deduced template name.
YES, it works! I just didn't realized you could only use it inside the static ifs, thanks for pointing that out! isInstanceOf( alias Template, T ) is nice but lacks support for expressions directly: but that ain't a big deal, example: struct Pair( T1, T2 ) {...} template isPair( alias T ) { static if( is( T ) ) { enum isPair = isInstanceOf!( Pair, T ); } else { enum isPair = isInstanceOf!( Pair, typeof( T ) ); //Must add this to support expressions. } } //Returns the type of the first term of the pair. template FirstType( alias T ) if( isPair!T ) { static if( is( T _: Pair!Args, Args... ) ) { alias FirstType = Args[ 0 ]; } else { alias FirstType = FirstType!( typeof( T ); } } The D programming language ROCKS :).
Jan 20 2013
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/20/13, Phil Lavoie <maidenphil hotmail.com> wrote:
 Imagine you have something like this:

 struct MyParamType( T1, T2 ) { ... }

 and then a compound:

 struct MyCoumpound( T ) if( isMyParamType!T ) { ... }
Use isInstanceOf in std.traits: struct MyCoumpound( T ) if( isInstanceOf!(MyParamType, T) ) { ... } On 1/20/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 is(T _ : MyParamType!U, U...)
 ( '_' just to tell someone reading the code this part is not used)
This won't be necessary in the next release thanks to a pull by Kenji, you will be able to use: is(T : MyParamType!U, U...)
Jan 20 2013
parent "Phil Lavoie" <maidenphil hotmail.com> writes:
On Sunday, 20 January 2013 at 15:59:45 UTC, Andrej Mitrovic wrote:
 On 1/20/13, Phil Lavoie <maidenphil hotmail.com> wrote:
 Imagine you have something like this:

 struct MyParamType( T1, T2 ) { ... }

 and then a compound:

 struct MyCoumpound( T ) if( isMyParamType!T ) { ... }
Use isInstanceOf in std.traits: struct MyCoumpound( T ) if( isInstanceOf!(MyParamType, T) ) { ... } On 1/20/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 is(T _ : MyParamType!U, U...)
 ( '_' just to tell someone reading the code this part is not 
 used)
This won't be necessary in the next release thanks to a pull by Kenji, you will be able to use: is(T : MyParamType!U, U...)
Nice, I am glad to learn it's in the stdlib.
Jan 20 2013
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Jan 20, 2013 at 4:59 PM, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:
 This won't be necessary in the next release thanks to a pull by Kenji,
 you will be able to use:
 is(T : MyParamType!U, U...)
I just rebuild DMD 2.062 from git head, not there yet... Oh well.
Jan 20 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/20/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 On Sun, Jan 20, 2013 at 4:59 PM, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:
 This won't be necessary in the next release thanks to a pull by Kenji,
 you will be able to use:
 is(T : MyParamType!U, U...)
I just rebuild DMD 2.062 from git head, not there yet... Oh well.
My bad, it wasn't pulled yet: https://github.com/D-Programming-Language/dmd/pull/1255 Apologies for taking your time on building DMD.
Jan 20 2013
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Jan 20, 2013 at 5:23 PM, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:
 On 1/20/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 On Sun, Jan 20, 2013 at 4:59 PM, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:
 This won't be necessary in the next release thanks to a pull by Kenji,
 you will be able to use:
 is(T : MyParamType!U, U...)
I just rebuild DMD 2.062 from git head, not there yet... Oh well.
My bad, it wasn't pulled yet: https://github.com/D-Programming-Language/dmd/pull/1255 Apologies for taking your time on building DMD.
What? No need to apologize! It's just a small script I launch once or twice a week. It clones the github repos and builds everything. I just type `bash regenerate_dmd.sh` and wait a few minutes while GCC compiles happily.
Jan 20 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 1/20/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 What? No need to apologize! It's just a small script I launch once or
 twice a week. It clones the github repos and builds everything. I just
 type `bash regenerate_dmd.sh` and wait a few minutes while GCC
 compiles happily.
Is this something taken from the DWiki? If not, it might be a good idea to amend the current Posix build docs and maybe add a link to your script: http://wiki.dlang.org/Building_DMD I use something similar on win32 where I can build DMD-git very quickly.
Jan 20 2013
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Jan 20, 2013 at 7:33 PM, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:
 On 1/20/13, Philippe Sigaud <philippe.sigaud gmail.com> wrote:
 What? No need to apologize! It's just a small script I launch once or
 twice a week. It clones the github repos and builds everything. I just
 type `bash regenerate_dmd.sh` and wait a few minutes while GCC
 compiles happily.
Is this something taken from the DWiki? If not, it might be a good idea to amend the current Posix build docs and maybe add a link to your script: http://wiki.dlang.org/Building_DMD I use something similar on win32 where I can build DMD-git very quickly.
I just use the dlang-workspace script that was posted some weeks ago, wrapped in another script to pull the latest dlang-workspace, should it ever change. It's all hardcoded, because I'm just discovering bash scripts. So, nothing that should be on a wiki :) The dlang-workspace/posix/gen.sh script itself, which does all the hard work, could maybe be posted. But I'm not its author...
Jan 20 2013