Thread overview | ||||||
---|---|---|---|---|---|---|
|
December 08, 2018 cannot use local f as parameter to non-global template | ||||
---|---|---|---|---|
| ||||
Hi, I'm wondering about why this happens in a certain situation and not another. I have the following code: struct Holder(alias fun) { alias T = typeof(fun()); T get() { return fun(); } alias get this; } template match(handlers...) { auto match(T)(T holder) { return handlers[0](holder); } } void main() { int f() { return i7 } auto value = Holder!f().match!( (int a) => f() ); } This compiles fine. However, if I change the match template to: template match(handlers...) { auto match(alias f)(Holder!f holder) { return handlers[0](holder); } } Notice the template parameter of the eponymous match is an alias now, and the function parameter is typed as a Holder. The error you get is basically because of bug 5710 [0] I guess. But I'm confused as to why the same thing doesn't then happen when using match(T) as opposed to match(alias f)? I can work around it by have a template constraint on match of course. But still curious why one version works and the other not, they both have to access the same frame+context data at the end of the day. [0]: https://issues.dlang.org/show_bug.cgi?id=5710 |
December 08, 2018 Re: cannot use local f as parameter to non-global template | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Saturday, 8 December 2018 at 09:57:29 UTC, aliak wrote:
> This compiles fine. However, if I change the match template to:
>
> template match(handlers...) {
> auto match(alias f)(Holder!f holder) {
> return handlers[0](holder);
> }
> }
>
> Notice the template parameter of the eponymous match is an alias now, and the function parameter is typed as a Holder.
The "de-sugared" version of your second `match` function looks like this:
template match(handlers...) {
template match(alias f) {
auto match(Holder!f holder) {
return handlers[0](holder);
}
}
}
Notice the second template nested inside the first. That's the "non-gloal template" the error is complaining about.
|
December 10, 2018 Re: cannot use local f as parameter to non-global template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Saturday, 8 December 2018 at 14:21:01 UTC, Paul Backus wrote:
> On Saturday, 8 December 2018 at 09:57:29 UTC, aliak wrote:
>> This compiles fine. However, if I change the match template to:
>>
>> template match(handlers...) {
>> auto match(alias f)(Holder!f holder) {
>> return handlers[0](holder);
>> }
>> }
>>
>> Notice the template parameter of the eponymous match is an alias now, and the function parameter is typed as a Holder.
>
> The "de-sugared" version of your second `match` function looks like this:
>
> template match(handlers...) {
> template match(alias f) {
> auto match(Holder!f holder) {
> return handlers[0](holder);
> }
> }
> }
>
> Notice the second template nested inside the first. That's the "non-gloal template" the error is complaining about.
Ah, that's a good way of breaking it down. But ok, so then the other version would be lowered to:
template match(handlers...) {
template match(T) {
auto match(T holder) {
return handlers[0](holder);
}
}
}
So now the second template is accessing a T, which is actually a Holder!f right? But doing that makes it "work". Even though the number of "contexts" needed to execute "handlers[0](holder)" is the same, right?
|
December 10, 2018 Re: cannot use local f as parameter to non-global template | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Monday, 10 December 2018 at 16:15:36 UTC, aliak wrote:
>
> Ah, that's a good way of breaking it down. But ok, so then the other version would be lowered to:
>
> template match(handlers...) {
> template match(T) {
> auto match(T holder) {
> return handlers[0](holder);
> }
> }
> }
>
> So now the second template is accessing a T, which is actually a Holder!f right? But doing that makes it "work". Even though the number of "contexts" needed to execute "handlers[0](holder)" is the same, right?
Holder!f is a type, not a delegate, so passing it as a parameter to a non-global template is fine. Issue 5710 only applies to delegates passed directly as parameters.
Trying to reason about the "number of contexts" required is a waste of time. There's no logical, principled reason why one works and the other doesn't. It's purely an artifact of details in the compiler implementation.
|
Copyright © 1999-2021 by the D Language Foundation