digitalmars.D.learn - Where does the template parameter E come from?
- simendsjo (39/39) Mar 28 2011 When running compose with two arguments, the implementation uses the
- simendsjo (4/42) Mar 28 2011 I think I get it.
- David Nadlinger (17/23) Mar 28 2011 doIt is a function template, so E will be deduced to be whatever type
- simendsjo (3/26) Mar 28 2011 Thanks. That seems like a good way of mentally mapping template usage
- David Nadlinger (7/37) Mar 28 2011 Even more, due to the eponymous template »trick«, there is almost no
When running compose with two arguments, the implementation uses the template parameter E. I don't understand what's going on here as E isn't submitted to the template - what type is E? I've also seen this in unary/binaryFun using ElementType. template compose(fun...) { alias composeImpl!(fun).doIt compose; } // Implementation of compose template composeImpl(fun...) { static if (fun.length == 1) { static if (is(typeof(fun[0]) : string)) alias unaryFun!(fun[0]) doIt; else alias fun[0] doIt; } else static if (fun.length == 2) { // starch static if (is(typeof(fun[0]) : string)) alias unaryFun!(fun[0]) fun0; else alias fun[0] fun0; static if (is(typeof(fun[1]) : string)) alias unaryFun!(fun[1]) fun1; else alias fun[1] fun1; // protein: the core composition operation typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a) { return fun0(fun1(a)); } } else { // protein: assembling operations alias composeImpl!(fun[0], composeImpl!(fun[1 .. $]).doIt).doIt doIt; } }
Mar 28 2011
On 28.03.2011 16:54, simendsjo wrote:When running compose with two arguments, the implementation uses the template parameter E. I don't understand what's going on here as E isn't submitted to the template - what type is E? I've also seen this in unary/binaryFun using ElementType. template compose(fun...) { alias composeImpl!(fun).doIt compose; } // Implementation of compose template composeImpl(fun...) { static if (fun.length == 1) { static if (is(typeof(fun[0]) : string)) alias unaryFun!(fun[0]) doIt; else alias fun[0] doIt; } else static if (fun.length == 2) { // starch static if (is(typeof(fun[0]) : string)) alias unaryFun!(fun[0]) fun0; else alias fun[0] fun0; static if (is(typeof(fun[1]) : string)) alias unaryFun!(fun[1]) fun1; else alias fun[1] fun1; // protein: the core composition operation typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a) { return fun0(fun1(a)); } } else { // protein: assembling operations alias composeImpl!(fun[0], composeImpl!(fun[1 .. $]).doIt).doIt doIt; } }I think I get it. doIt becomes the function being called. So E is the type of the parameter being used when calling compose.
Mar 28 2011
On 3/28/11 4:54 PM, simendsjo wrote:When running compose with two arguments, the implementation uses the template parameter E. I don't understand what's going on here as E isn't submitted to the template - what type is E? […] typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a) { […] }doIt is a function template, so E will be deduced to be whatever type the passed argument is – you won't notice the extra »template layer« as E is automatically inferred from the argument. For better understanding, you might want to look at the definition like this: --- template composeImpl(fun...) { […] template doIt(E) { typeof({ E a; return fun0(fun1(a)); }()) doIt(E a) { […] } } } --- David
Mar 28 2011
On 28.03.2011 17:07, David Nadlinger wrote:On 3/28/11 4:54 PM, simendsjo wrote:Thanks. That seems like a good way of mentally mapping template usage until it comes more naturally.When running compose with two arguments, the implementation uses the template parameter E. I don't understand what's going on here as E isn't submitted to the template - what type is E? […] typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a) { […] }doIt is a function template, so E will be deduced to be whatever type the passed argument is – you won't notice the extra »template layer« as E is automatically inferred from the argument. For better understanding, you might want to look at the definition like this: --- template composeImpl(fun...) { […] template doIt(E) { typeof({ E a; return fun0(fun1(a)); }()) doIt(E a) { […] } } } --- David
Mar 28 2011
On 3/28/11 5:14 PM, simendsjo wrote:On 28.03.2011 17:07, David Nadlinger wrote:Even more, due to the eponymous template »trick«, there is almost no difference between the forms – with the important exception being that function templates enjoy IFTI (implicit function template instantiation), the feature which allows you to omit the type parameter(s) if it can be deduced from the arguments. DavidOn 3/28/11 4:54 PM, simendsjo wrote:Thanks. That seems like a good way of mentally mapping template usage until it comes more naturally.When running compose with two arguments, the implementation uses the template parameter E. I don't understand what's going on here as E isn't submitted to the template - what type is E? […] typeof({ E a; return fun0(fun1(a)); }()) doIt(E)(E a) { […] }doIt is a function template, so E will be deduced to be whatever type the passed argument is – you won't notice the extra »template layer« as E is automatically inferred from the argument. For better understanding, you might want to look at the definition like this: --- template composeImpl(fun...) { […] template doIt(E) { typeof({ E a; return fun0(fun1(a)); }()) doIt(E a) { […] } } } --- David
Mar 28 2011