www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - template sequence parameters treats member functions differently?

reply aliak <something something.com> writes:
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
Jun 24 2018
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Jun 25 2018
parent reply aliak <something something.com> writes:
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 :)
Jun 25 2018
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Jun 25 2018
parent aliak <something something.com> writes:
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
Jun 25 2018