Thread overview
template sequence parameters treats member functions differently?
Jun 24, 2018
aliak
Jun 25, 2018
aliak
Jun 26, 2018
aliak
June 24, 2018
Hi, I'm having some issues with template sequence parameters, it seems they are not typed as delegates inside a template, but are outside. I.e.

template T(V...) {
    alias T = typeof(&V[0]);
}

struct S { void f() {} }
S s;

pragma(msg, T!(s.f)); // void function()
pragma(msg, typeof(&s.f)); // void delegate()

How come the output is different? Is it supposed to be the same?

What I'm trying to do is write a template that can give me a tuple of types for all values of the sequence passed in, so that I can index in to the type tuple. Seems to work well except for this member function part, working source here:

https://run.dlang.io/is/TBXHlY

Specifically the commented out line is what I would like to be able to get working if possible.

Thanks for any help,
- Ali



June 25, 2018
On 6/24/18 5:19 PM, aliak wrote:
> Hi, I'm having some issues with template sequence parameters, it seems they are not typed as delegates inside a template, but are outside. I.e.
> 
> template T(V...) {
>      alias T = typeof(&V[0]);
> }
> 
> struct S { void f() {} }
> S s;
> 
> pragma(msg, T!(s.f)); // void function()
> pragma(msg, typeof(&s.f)); // void delegate()
> 
> How come the output is different? Is it supposed to be the same?

No, because the alias is an alias to the function, not the delegate.

The act of taking the address creates the delegate, where the delegate's ptr is the context pointer (i.e. s), and the funcptr is the function that accepts the pointer (i.e. S.f).

When you pass in s.f to an alias, you are actually passing in S.f. It's the fact that you are looking in the *namespace* of s when you do the alias. The &s.f is special for the compiler, and can't be deferred to later.

BUT, I'm thinking this may be fixable, as it's inconsistent with inner functions:

auto foo(alias x)() { return x(); }

struct S
{
   int bar() { return 42; }

   // int baz() { return foo!bar; } // nope
}

void main()
{
   S s;

   int bar() { return 42; }

   assert(foo!bar() == 42); // ok
   // assert(foo!(s.bar) == 42); // nope

   int baz() { return s.bar; }
   assert(foo!baz() == 42); // ok!
}

I don't see any reason why the alias is to the function and not the contexted function. I don't see how it's any different from the ones which use inner functions.

-Steve
June 25, 2018
On Monday, 25 June 2018 at 15:06:42 UTC, Steven Schveighoffer wrote:
> On 6/24/18 5:19 PM, aliak wrote:
>> [...]
>
> No, because the alias is an alias to the function, not the delegate.
>
> The act of taking the address creates the delegate, where the delegate's ptr is the context pointer (i.e. s), and the funcptr is the function that accepts the pointer (i.e. S.f).
>
> When you pass in s.f to an alias, you are actually passing in S.f. It's the fact that you are looking in the *namespace* of s when you do the alias. The &s.f is special for the compiler, and can't be deferred to later.

Ahh, I see. Ah well. So not really much i can do here with this then I guess. Thanks for explaining though!

>
> BUT, I'm thinking this may be fixable, as it's inconsistent with inner functions:
>
> auto foo(alias x)() { return x(); }
>
> struct S
> {
>    int bar() { return 42; }
>
>    // int baz() { return foo!bar; } // nope
> }
>
> void main()
> {
>    S s;
>
>    int bar() { return 42; }
>
>    assert(foo!bar() == 42); // ok
>    // assert(foo!(s.bar) == 42); // nope
>
>    int baz() { return s.bar; }
>    assert(foo!baz() == 42); // ok!
> }
>
> I don't see any reason why the alias is to the function and not the contexted function. I don't see how it's any different from the ones which use inner functions.
>
> -Steve

I can only agree - me no see either. And having no clue as to how the compiler is implemented, I cannot even conjecture :)

June 25, 2018
On 6/25/18 2:51 PM, aliak wrote:
> On Monday, 25 June 2018 at 15:06:42 UTC, Steven Schveighoffer wrote:

>> I don't see any reason why the alias is to the function and not the contexted function. I don't see how it's any different from the ones which use inner functions.
> 
> I can only agree - me no see either. And having no clue as to how the compiler is implemented, I cannot even conjecture :)
> 

Well, it's worth an enhancement request in any case.

-Steve
June 26, 2018
On Monday, 25 June 2018 at 18:59:37 UTC, Steven Schveighoffer wrote:
> On 6/25/18 2:51 PM, aliak wrote:
>> On Monday, 25 June 2018 at 15:06:42 UTC, Steven Schveighoffer wrote:
>
>>> I don't see any reason why the alias is to the function and not the contexted function. I don't see how it's any different from the ones which use inner functions.
>> 
>> I can only agree - me no see either. And having no clue as to how the compiler is implemented, I cannot even conjecture :)
>> 
>
> Well, it's worth an enhancement request in any case.
>
> -Steve

doneo: https://issues.dlang.org/show_bug.cgi?id=19026