Re: Forwarding calls to objects of another type

2017-04-19 Thread Johan Fjeldtvedt via Digitalmars-d-learn

On Tuesday, 11 April 2017 at 02:01:19 UTC, Nicholas Wilson wrote:

On Monday, 10 April 2017 at 21:27:34 UTC, Basile B. wrote:
2) This is about the reduce templates. As I've commented, I 
can't use a template lambda with reduce, but I can use a 
lambda taking ints as arguments. Why is this? The error 
message I get when using the template lambda is:


"template instance reduce!((a, b) => a + b) cannot use local 
'__lambda1' as parameter to non-global template reduce(alias 
fun)()"


No idea for this.


The use of the global identity template will fix this:

see 
https://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/


Thanks, that did work. I think I understand the point about UFCS 
lookup rules, but it still seems strange (it was at least 
surprising) that I couldn't use the template (a, b) => a + b in 
place of (int a, int b) => a + b.


Re: Forwarding calls to objects of another type

2017-04-19 Thread Johan Fjeldtvedt via Digitalmars-d-learn

On Monday, 10 April 2017 at 21:27:34 UTC, Basile B. wrote:
On Monday, 10 April 2017 at 21:04:10 UTC, Johan Fjeldtvedt 
wrote:

[...]


One way:

[...]


Thanks for the reply. The traits way of doing it seems to be what 
I want. :)



[...]


[...]




Re: Forwarding calls to objects of another type

2017-04-10 Thread Nicholas Wilson via Digitalmars-d-learn

On Monday, 10 April 2017 at 21:27:34 UTC, Basile B. wrote:
2) This is about the reduce templates. As I've commented, I 
can't use a template lambda with reduce, but I can use a 
lambda taking ints as arguments. Why is this? The error 
message I get when using the template lambda is:


"template instance reduce!((a, b) => a + b) cannot use local 
'__lambda1' as parameter to non-global template reduce(alias 
fun)()"


No idea for this.


The use of the global identity template will fix this:

see 
https://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/


Re: Forwarding calls to objects of another type

2017-04-10 Thread Basile B. via Digitalmars-d-learn

On Monday, 10 April 2017 at 21:04:10 UTC, Johan Fjeldtvedt wrote:
I have a couple of questions related to the following code: 
https://gist.github.com/Jaffe-/b027287a884fc2e173a65601ec242676


1) This is a very simplified example, but what I'm trying to do 
here is to call `foo` on each object in `Container.ss` contains 
when `foo` is called, and likewise for `bar`. To do this 
without having to repeat the foreach loop in every member 
function, I made the `call_for_each` template. However, I found 
no other way to pull this off (without using string mixins) 
than to also add the `call` template in the S struct. At first 
I thought it would be possible to write `s.func(args)` in 
`call_for_each`, but that will try to look up func as a member 
in the struct.


Is there a more common / idiomatic way of doing this? In C++ 
this would be solved by using a member function pointer as a 
template argument, but as far as I understand D uses delegates 
(which are already bound to an instance) instead?


One way:

struct S {
int x[];

void foo(int x) {
this.x ~= x;
}

void bar() {
writeln("Contains: ", x);
}

auto call(alias func, T...)(T args) {
return func(args);
}

auto reduce(alias func)() {
return x.reduce!(func);
}
}

class Container {
S[10] ss;

void dispatch(string func, T...)(T args) {
foreach(ref s; ss) {
__traits(getMember, s, func)(args);
}
}

auto reduce(alias func)() {
return ss[]
.map!(t => t.reduce!func)
.reduce!(func);
}

}

void main() {
auto test = new Container();

test.dispatch!"foo"(10);
test.dispatch!"foo"(20);
test.dispatch!"foo"(30);
test.dispatch!"bar"();
//auto x = test.reduce!((a, b) => a + b);
auto x = test.reduce!((int a, int b) => a + b);  // Compiles
writeln(x);
}

Another way would be to take the delegate of one instance and to 
patch the pointer to the instance for each instance (because the 
member of a delegate can be changed: .ptr -> instance, .funcptr 
-> static address of the function). But it's less clean.


2) This is about the reduce templates. As I've commented, I 
can't use a template lambda with reduce, but I can use a lambda 
taking ints as arguments. Why is this? The error message I get 
when using the template lambda is:


"template instance reduce!((a, b) => a + b) cannot use local 
'__lambda1' as parameter to non-global template reduce(alias 
fun)()"


No idea for this.