digitalmars.D.learn - Where does the template parameter E come from?
- simendsjo <simen.endsjo pandavre.com> Mar 28 2011
- simendsjo <simen.endsjo pandavre.com> Mar 28 2011
- David Nadlinger <see klickverbot.at> Mar 28 2011
- simendsjo <simen.endsjo pandavre.com> Mar 28 2011
- David Nadlinger <see klickverbot.at> Mar 28 2011
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: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
Thanks. That seems like a good way of mentally mapping template usage until it comes more naturally.
Mar 28 2011
On 3/28/11 5:14 PM, simendsjo wrote:On 28.03.2011 17:07, David Nadlinger wrote: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
Thanks. That seems like a good way of mentally mapping template usage until it comes more naturally.
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. David
Mar 28 2011









simendsjo <simen.endsjo pandavre.com> 