Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
March 28, 2011 Where does the template parameter E come from? | ||||
---|---|---|---|---|
| ||||
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; } } |
March 28, 2011 Re: Where does the template parameter E come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | 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.
|
March 28, 2011 Re: Where does the template parameter E come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | 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
|
March 28, 2011 Re: Where does the template parameter E come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | 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.
|
March 28, 2011 Re: Where does the template parameter E come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | 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
|
Copyright © 1999-2021 by the D Language Foundation