www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - instantiate each of a tuple of templates (Take 2)

reply "John Colvin" <john.loughran.colvin gmail.com> writes:
template a(T ...)
{
     void a(R r)
     {
         //want to get a tuple of
         //the members of T, each
         //instantiated with R.

         //do some RT stuff
     }
}

Is this possible?

Whatever I try, I keep running in to "cannot use local as 
parameter to non-global template" errors, which I understand is 
to do with context pointers
However, this is all compile-time work based entirely on types, 
there should be no need for any context pointers.
Aug 01 2013
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin wrote:
 template a(T ...)
 {
     void a(R r)
     {
         //want to get a tuple of
         //the members of T, each
         //instantiated with R.

         //do some RT stuff
     }
 }

 Is this possible?

 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I understand is 
 to do with context pointers
 However, this is all compile-time work based entirely on types, 
 there should be no need for any context pointers.
A static foreach should do the trick. (code not actually tested) void a(R r) //void? Not Tuple!T ? { Tuple!T ret foreach(i, Type; T) { ret[i] = r; } return ret; } Is this what you want? This assumes that every member or T is a type, and not a name.
Aug 01 2013
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin wrote:
 ...
Does this help http://dpaste.dzfl.pl/fe533f7a ?
Aug 01 2013
prev sibling next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin wrote:
 template a(T ...)
 {
     void a(R r)
     {
         //want to get a tuple of
         //the members of T, each
         //instantiated with R.

         //do some RT stuff
     }
 }

 Is this possible?

 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I understand is 
 to do with context pointers
 However, this is all compile-time work based entirely on types, 
 there should be no need for any context pointers.
Still not sure what you want, but you may want to look into adjoin and staticMap.
Aug 01 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 1 August 2013 at 14:57:07 UTC, monarch_dodra wrote:
 On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin wrote:
 template a(T ...)
 {
    void a(R r)
    {
        //want to get a tuple of
        //the members of T, each
        //instantiated with R.

        //do some RT stuff
    }
 }

 Is this possible?

 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I understand 
 is to do with context pointers
 However, this is all compile-time work based entirely on 
 types, there should be no need for any context pointers.
Still not sure what you want, but you may want to look into adjoin and staticMap.
Sorry, now I've thought about it some more it appears I was asking the wrong question completely! Here's the situation (you might recognise the pattern from std.algorithm.map): template a(funs...) { auto a(R)(R r) { alias /*something*/ nonVoidFuns; alias /*something*/ voidFuns; //do stuff with nonVoidFuns and voidFuns applied to r } } so i need to find the return type of each fun, when called with something of type R (bearing in mind that fun!R may not be the same type as fun(r) as fun might be T fun(T)(T[] a), then filter funs to seperate the void functions from the non-void ones. Or something else to that effect. I've tried several things with std.typetuple.Filter but nothing seems to work.
Aug 01 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 1 August 2013 at 15:08:53 UTC, John Colvin wrote:
 On Thursday, 1 August 2013 at 14:57:07 UTC, monarch_dodra wrote:
 On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin wrote:
 template a(T ...)
 {
   void a(R r)
   {
       //want to get a tuple of
       //the members of T, each
       //instantiated with R.

       //do some RT stuff
   }
 }

 Is this possible?

 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I understand 
 is to do with context pointers
 However, this is all compile-time work based entirely on 
 types, there should be no need for any context pointers.
Still not sure what you want, but you may want to look into adjoin and staticMap.
Sorry, now I've thought about it some more it appears I was asking the wrong question completely! Here's the situation (you might recognise the pattern from std.algorithm.map): template a(funs...) { auto a(R)(R r) { alias /*something*/ nonVoidFuns; alias /*something*/ voidFuns; //do stuff with nonVoidFuns and voidFuns applied to r } } so i need to find the return type of each fun, when called with something of type R (bearing in mind that fun!R may not be the same type as fun(r) as fun might be T fun(T)(T[] a), then filter funs to seperate the void functions from the non-void ones. Or something else to that effect. I've tried several things with std.typetuple.Filter but nothing seems to work.
Any ideas anyone? It seems like something that should be easily done somehow.
Aug 02 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 2 August 2013 at 10:54:06 UTC, John Colvin wrote:
 On Thursday, 1 August 2013 at 15:08:53 UTC, John Colvin wrote:
 On Thursday, 1 August 2013 at 14:57:07 UTC, monarch_dodra 
 wrote:
 On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin wrote:
 template a(T ...)
 {
  void a(R r)
  {
      //want to get a tuple of
      //the members of T, each
      //instantiated with R.

      //do some RT stuff
  }
 }

 Is this possible?

 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I understand 
 is to do with context pointers
 However, this is all compile-time work based entirely on 
 types, there should be no need for any context pointers.
Still not sure what you want, but you may want to look into adjoin and staticMap.
Sorry, now I've thought about it some more it appears I was asking the wrong question completely! Here's the situation (you might recognise the pattern from std.algorithm.map): template a(funs...) { auto a(R)(R r) { alias /*something*/ nonVoidFuns; alias /*something*/ voidFuns; //do stuff with nonVoidFuns and voidFuns applied to r } } so i need to find the return type of each fun, when called with something of type R (bearing in mind that fun!R may not be the same type as fun(r) as fun might be T fun(T)(T[] a), then filter funs to seperate the void functions from the non-void ones. Or something else to that effect. I've tried several things with std.typetuple.Filter but nothing seems to work.
Any ideas anyone? It seems like something that should be easily done somehow.
//---- import std.stdio, std.typetuple; template isVoidArg(U) { template isVoid(alias F) { enum isVoid = is(typeof(F(U.init)) == void); } alias isVoidArg = isVoid; } template isNonVoidArg(U) { template isNonVoid(alias F) { enum isNonVoid = is(typeof({auto a = F(U.init);})); } alias isNonVoidArg = isNonVoid; } template isErrorArg(U) { template isError(alias F) { enum isError = !is(typeof(F(U.init))); } alias isErrorArg = isError; } template a(funs...) { auto a(R)(R r) { alias nonVoidFuns = Filter!(isNonVoidArg!R, funs); alias voidFuns = Filter!(isVoidArg!R, funs); alias voidErrorFuns = Filter!(isErrorArg!R, funs); import std.functional : adjoin; writeln("Calling all non voids!"); adjoin!nonVoidFuns(r); writeln("Calling all voids!"); adjoin!voidFuns(r); } } void fun1(string i) { writeln("fun1 ", i); } int fun2() { writeln("fun2"); return int.min; } void fun3(int i) { writeln("fun3 ", i); } int fun4(int i) { writeln("fun4 ", i); return i; } void main() { a!(fun1, fun2, fun3, fun4)(99); } //---- Calling all non voids! fun4 5 Calling all voids! fun3 5 //---- Is this what you want?
Aug 02 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 2 August 2013 at 11:26:41 UTC, monarch_dodra wrote:
 On Friday, 2 August 2013 at 10:54:06 UTC, John Colvin wrote:
 On Thursday, 1 August 2013 at 15:08:53 UTC, John Colvin wrote:
 On Thursday, 1 August 2013 at 14:57:07 UTC, monarch_dodra 
 wrote:
 On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin 
 wrote:
 template a(T ...)
 {
 void a(R r)
 {
     //want to get a tuple of
     //the members of T, each
     //instantiated with R.

     //do some RT stuff
 }
 }

 Is this possible?

 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I 
 understand is to do with context pointers
 However, this is all compile-time work based entirely on 
 types, there should be no need for any context pointers.
Still not sure what you want, but you may want to look into adjoin and staticMap.
Sorry, now I've thought about it some more it appears I was asking the wrong question completely! Here's the situation (you might recognise the pattern from std.algorithm.map): template a(funs...) { auto a(R)(R r) { alias /*something*/ nonVoidFuns; alias /*something*/ voidFuns; //do stuff with nonVoidFuns and voidFuns applied to r } } so i need to find the return type of each fun, when called with something of type R (bearing in mind that fun!R may not be the same type as fun(r) as fun might be T fun(T)(T[] a), then filter funs to seperate the void functions from the non-void ones. Or something else to that effect. I've tried several things with std.typetuple.Filter but nothing seems to work.
Any ideas anyone? It seems like something that should be easily done somehow.
//---- import std.stdio, std.typetuple; template isVoidArg(U) { template isVoid(alias F) { enum isVoid = is(typeof(F(U.init)) == void); } alias isVoidArg = isVoid; } template isNonVoidArg(U) { template isNonVoid(alias F) { enum isNonVoid = is(typeof({auto a = F(U.init);})); } alias isNonVoidArg = isNonVoid; } template isErrorArg(U) { template isError(alias F) { enum isError = !is(typeof(F(U.init))); } alias isErrorArg = isError; } template a(funs...) { auto a(R)(R r) { alias nonVoidFuns = Filter!(isNonVoidArg!R, funs); alias voidFuns = Filter!(isVoidArg!R, funs); alias voidErrorFuns = Filter!(isErrorArg!R, funs); import std.functional : adjoin; writeln("Calling all non voids!"); adjoin!nonVoidFuns(r); writeln("Calling all voids!"); adjoin!voidFuns(r); } } void fun1(string i) { writeln("fun1 ", i); } int fun2() { writeln("fun2"); return int.min; } void fun3(int i) { writeln("fun3 ", i); } int fun4(int i) { writeln("fun4 ", i); return i; } void main() { a!(fun1, fun2, fun3, fun4)(99); } //---- Calling all non voids! fun4 5 Calling all voids! fun3 5 //---- Is this what you want?
Thankyou, yes that's exactly right. Are all types guaranteed to have a working .init value? I can't think of any way not to, but I just want to be sure.
Aug 02 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 2 August 2013 at 12:37:00 UTC, John Colvin wrote:
 Are all types guaranteed to have a working .init value? I can't 
 think of any way not to, but I just want to be sure.
Not sure what you mean by "working" but there is a hard guarantee that for any type "T.init" will compile and result in some value. That was the key idea behind .init and reason why default constructors are prohibited for structs.
Aug 02 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 2 August 2013 at 12:47:24 UTC, Dicebot wrote:
 On Friday, 2 August 2013 at 12:37:00 UTC, John Colvin wrote:
 Are all types guaranteed to have a working .init value? I 
 can't think of any way not to, but I just want to be sure.
Not sure what you mean by "working" but there is a hard guarantee that for any type "T.init" will compile and result in some value. That was the key idea behind .init and reason why default constructors are prohibited for structs.
Thanks, that's how I thought it worked.
Aug 02 2013
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 2 August 2013 at 12:37:00 UTC, John Colvin wrote:
 On Friday, 2 August 2013 at 11:26:41 UTC, monarch_dodra wrote:
 Is this what you want?
Thankyou, yes that's exactly right. Are all types guaranteed to have a working .init value? I can't think of any way not to, but I just want to be sure.
Yes, but there's a catch: T.init is an RValue, so if you have "foo(ref T)", then: foo(T.init) won't compile (and rightly so). user denis-sh proposed the lvalueOf functionional "trait": https://github.com/D-Programming-Language/phobos/pull/1261 property ref T lvalueOf(T)(inout int = 0); This can be used *only* at compile time (no body, so it won't link), and is meant to be used in constraints/static ifs. In this case: static assert(is(typeof(foo(lvalueOf!T)))); *Will* work.
Aug 02 2013
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 2 August 2013 at 11:26:41 UTC, monarch_dodra wrote:
 On Friday, 2 August 2013 at 10:54:06 UTC, John Colvin wrote:
 On Thursday, 1 August 2013 at 15:08:53 UTC, John Colvin wrote:
 On Thursday, 1 August 2013 at 14:57:07 UTC, monarch_dodra 
 wrote:
 On Thursday, 1 August 2013 at 12:50:42 UTC, John Colvin 
 wrote:
 template a(T ...)
 {
 void a(R r)
 {
     //want to get a tuple of
     //the members of T, each
     //instantiated with R.

     //do some RT stuff
 }
 }

 Is this possible?

 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I 
 understand is to do with context pointers
 However, this is all compile-time work based entirely on 
 types, there should be no need for any context pointers.
Still not sure what you want, but you may want to look into adjoin and staticMap.
Sorry, now I've thought about it some more it appears I was asking the wrong question completely! Here's the situation (you might recognise the pattern from std.algorithm.map): template a(funs...) { auto a(R)(R r) { alias /*something*/ nonVoidFuns; alias /*something*/ voidFuns; //do stuff with nonVoidFuns and voidFuns applied to r } } so i need to find the return type of each fun, when called with something of type R (bearing in mind that fun!R may not be the same type as fun(r) as fun might be T fun(T)(T[] a), then filter funs to seperate the void functions from the non-void ones. Or something else to that effect. I've tried several things with std.typetuple.Filter but nothing seems to work.
Any ideas anyone? It seems like something that should be easily done somehow.
//---- import std.stdio, std.typetuple; template isVoidArg(U) { template isVoid(alias F) { enum isVoid = is(typeof(F(U.init)) == void); } alias isVoidArg = isVoid; } template isNonVoidArg(U) { template isNonVoid(alias F) { enum isNonVoid = is(typeof({auto a = F(U.init);})); } alias isNonVoidArg = isNonVoid; } template isErrorArg(U) { template isError(alias F) { enum isError = !is(typeof(F(U.init))); } alias isErrorArg = isError; } template a(funs...) { auto a(R)(R r) { alias nonVoidFuns = Filter!(isNonVoidArg!R, funs); alias voidFuns = Filter!(isVoidArg!R, funs); alias voidErrorFuns = Filter!(isErrorArg!R, funs); import std.functional : adjoin; writeln("Calling all non voids!"); adjoin!nonVoidFuns(r); writeln("Calling all voids!"); adjoin!voidFuns(r); } } void fun1(string i) { writeln("fun1 ", i); } int fun2() { writeln("fun2"); return int.min; } void fun3(int i) { writeln("fun3 ", i); } int fun4(int i) { writeln("fun4 ", i); return i; } void main() { a!(fun1, fun2, fun3, fun4)(99); } //---- Calling all non voids! fun4 5 Calling all voids! fun3 5 //---- Is this what you want?
I just ran in to a problem with this. It can't work for anything other than global functions. void main() { int fun6(int i) { writeln("fun6 ", i); return i; } a!(fun6)(99); } std/typetuple.d(664): Error: template instance pred!(fun6) cannot use local 'fun6' as parameter to non-global template isVoidFun(alias fun) So it's back to that same problem again.
Aug 02 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 2 August 2013 at 12:58:08 UTC, John Colvin wrote:
 std/typetuple.d(664): Error: template instance pred!(fun6) 
 cannot use local 'fun6' as parameter to non-global template 
 isVoidFun(alias fun)

 So it's back to that same problem again.
That is probably my most hated error message ever... Anyway, it should work if "isVoidFun" is global (not nested) symbol, not "fun6". Are you sure about it?
Aug 02 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 2 August 2013 at 13:07:16 UTC, Dicebot wrote:
 On Friday, 2 August 2013 at 12:58:08 UTC, John Colvin wrote:
 std/typetuple.d(664): Error: template instance pred!(fun6) 
 cannot use local 'fun6' as parameter to non-global template 
 isVoidFun(alias fun)

 So it's back to that same problem again.
That is probably my most hated error message ever... Anyway, it should work if "isVoidFun" is global (not nested) symbol, not "fun6". Are you sure about it?
I'd made some changes before getting that error. Using monarch_dodra's code verbatim: void main() { void fun1(string i) { writeln("fun1 ", i); } a!(fun1)(99); } std/typetuple.d(664): Error: template instance pred!(fun1) cannot use local 'fun1' as parameter to non-global template isNonVoid(alias F) and a whole load more crap
Aug 02 2013
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 2 August 2013 at 12:58:08 UTC, John Colvin wrote:
 Is this what you want?
I just ran in to a problem with this. It can't work for anything other than global functions. void main() { int fun6(int i) { writeln("fun6 ", i); return i; } a!(fun6)(99); } std/typetuple.d(664): Error: template instance pred!(fun6) cannot use local 'fun6' as parameter to non-global template isVoidFun(alias fun) So it's back to that same problem again.
The "root" problem is that filter just isn't adapted here. If you don't mind writing "filter 2 (for example)" though... //-------- import std.stdio, std.typetuple; template isVoidArg(alias F, U) { enum isVoidArg = is(typeof(F(U.init)) == void); } template isNonVoidArg(alias F, U) { enum isNonVoidArg = is(typeof({auto a = F(U.init);})); } template isErrorArg(alias F, U) { enum isErrorArg = !is(typeof(F(U.init))); } template Filter2(alias pred, U, TList...) { static if (TList.length == 0) { alias Filter2 = TypeTuple!(); } else static if (TList.length == 1) { static if (pred!(TList[0], U)) alias Filter2 = TypeTuple!(TList[0]); else alias Filter2 = TypeTuple!(); } else { alias Filter2 = TypeTuple!( Filter2!(pred, U, TList[ 0 .. $/2]), Filter2!(pred, U, TList[$/2 .. $ ])); } } template a(funs...) { auto a(R)(R r) { alias nonVoidFuns = Filter2!(isNonVoidArg, R, funs); alias voidFuns = Filter2!(isVoidArg, R, funs); alias voidErrorFuns = Filter2!(isErrorArg, R, funs); import std.functional : adjoin; writeln("Calling all non voids!"); adjoin!nonVoidFuns(r); writeln("Calling all voids!"); adjoin!voidFuns(r); } } void main() { void fun1(string i) { writeln("fun1 ", i); } int fun2() { writeln("fun2"); return int.min; } void fun3(int i) { writeln("fun3 ", i); } int fun4(int i) { writeln("fun4 ", i); return i; } a!(fun1, fun2, fun3, fun4)(99); } //-------- The template names kind of suck though. You may want to change some of them.
Aug 02 2013
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 08/01/13 14:50, John Colvin wrote:
 template a(T ...)
 {
     void a(R r)
     {
         //want to get a tuple of
         //the members of T, each
         //instantiated with R.
 
         //do some RT stuff
     }
 }
 
 Is this possible?
 
 Whatever I try, I keep running in to "cannot use local as parameter to
non-global template" errors, which I understand is to do with context pointers
 However, this is all compile-time work based entirely on types, there should
be no need for any context pointers.
 
Always post real and complete (even if not working) code, as figuring out what the problem is can be harder than giving the solution... template RealTuple(A...) { alias RealTuple = A; } template a(T ...) { auto a(R)(R r) { //want to get a tuple of //the members of T, each //instantiated with R. mixin({ string m; foreach (I, _; T) m ~= "alias UGH"~I.stringof~" = T["~I.stringof~"];\n"; m ~= "alias TupleofTsBangR = RealTuple!("; foreach (I, _; T) m ~= (I?", ":"") ~ "UGH"~I.stringof~"!R"; return m ~ ");"; }()); // do some RT stuff TupleofTsBangR x; foreach (I, _; typeof(x)) x[I] = r; // etc import std.typecons; return tuple(x); } } (If this is what you were actually looking for then I hope somebody else has another solution; this approach is just too ugly...) artur
Aug 01 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 1 August 2013 at 15:06:50 UTC, Artur Skawina wrote:
 On 08/01/13 14:50, John Colvin wrote:
 template a(T ...)
 {
     void a(R r)
     {
         //want to get a tuple of
         //the members of T, each
         //instantiated with R.
 
         //do some RT stuff
     }
 }
 
 Is this possible?
 
 Whatever I try, I keep running in to "cannot use local as 
 parameter to non-global template" errors, which I understand 
 is to do with context pointers
 However, this is all compile-time work based entirely on 
 types, there should be no need for any context pointers.
 
Always post real and complete (even if not working) code, as figuring out what the problem is can be harder than giving the solution... template RealTuple(A...) { alias RealTuple = A; } template a(T ...) { auto a(R)(R r) { //want to get a tuple of //the members of T, each //instantiated with R. mixin({ string m; foreach (I, _; T) m ~= "alias UGH"~I.stringof~" = T["~I.stringof~"];\n"; m ~= "alias TupleofTsBangR = RealTuple!("; foreach (I, _; T) m ~= (I?", ":"") ~ "UGH"~I.stringof~"!R"; return m ~ ");"; }()); // do some RT stuff TupleofTsBangR x; foreach (I, _; typeof(x)) x[I] = r; // etc import std.typecons; return tuple(x); } } (If this is what you were actually looking for then I hope somebody else has another solution; this approach is just too ugly...) artur
sorry yeah I didnt think the question through before asking. I'm normally the one nagging for better example code when people ask questions! I did consider wading through everything with string mixins etc. but it seemed like a lot of effort for what (on the surface) is a simple problem. Anyhow, please see my response to monarch_dodra as I've revised my question somewhat
Aug 01 2013