digitalmars.D - Alias template parameters and runtime functions
- Peter Alexander (20/20) Oct 03 2010 This post has two questions:
- bearophile (23/38) Oct 03 2010 But that code works with dmd 2.049:
- Peter Alexander (31/35) Oct 03 2010 You're right!
- bearophile (24/25) Oct 03 2010 I have simplified your test case a little:
- Peter Alexander (1/1) Oct 03 2010 Ok, so with the test case sorted, how am I supposed to return the map ov...
This post has two questions:
1. What are the semantics of 'alias' template parameters when initialised using
runtime functions,
e.g.:
class Foo
{
int[] data;
int foo(int i) { return data[i]; }
auto allFoo()
{
auto fun = (int i) { return foo(i); };
// alternatively: auto fun = &this.foo; (same result)
return map!(fun)(iota(data.length));
}
}
This compiles, but gives you an access violation when you try to use it. Alias
is a compile time
construct (if I am not mistaken), so why does the compiler allow this?
2. How can I achieve what allFoo() above is trying to do? Obviously I could
just return data in this
trivial case, but imagine that foo(int) did something more complex, and I
didn't want to repeat the
logic of foo(int) in allFoo().
Thanks.
Oct 03 2010
Peter Alexander:
class Foo
{
int[] data;
int foo(int i) { return data[i]; }
auto allFoo()
{
auto fun = (int i) { return foo(i); };
// alternatively: auto fun = &this.foo; (same result)
return map!(fun)(iota(data.length));
}
}
This compiles, but gives you an access violation when you try to use it.
But that code works with dmd 2.049:
import std.algorithm: map, equal;
import std.range: iota;
class Foo {
int[] data;
this(int[] a) { this.data = a.dup; }
int foo(int i) { return data[i] * 2; }
auto allFoo1() {
auto fun = (int i) { return foo(i); };
return map!(fun)(iota(data.length));
}
auto allFoo2() {
return map!((int i){ return foo(i); })(iota(data.length));
}
}
void main() {
auto f = new Foo([1, 2, 3]);
assert(equal(f.allFoo1(), [2, 4, 6]));
assert(equal(f.allFoo2(), [2, 4, 6]));
}
Bye,
bearophile
Oct 03 2010
== Quote from bearophile (bearophileHUGS lycos.com)'s articleBut that code works with dmd 2.049: ... Bye, bearophileYou're right! That makes things even more curious then. I had noticed the problem in some more complex code and just assumed it would be the same in the simple code that I presented. That said, I have managed to create a slightly more complex example that *does* break. import std.algorithm: map, equal; import std.range: iota; import std.stdio; struct Bar { float[1] m; this(float a) { m = [a]; } } class Foo { Bar[1] m; this(Bar a) { m = [a]; } const foo(int i) { return m[i]; } const allFoo1() { auto fun = (int i) { return foo(i); }; return map!(fun)(iota(m.length)); } const allFoo2() { return map!((int i){ return foo(i); })(iota(m.length)); } } void main() { Foo f = new Foo(Bar(1)); assert(equal(f.allFoo1(), [Bar(1)])); assert(equal(f.allFoo2(), [Bar(1)])); }
Oct 03 2010
Peter Alexander:That said, I have managed to create a slightly more complex example that *does* break.I have simplified your test case a little: import std.algorithm: map; struct Bar { float[1] m; this(float a) { m[0] = a; } } class Foo { Bar[1] m; this(Bar a) { m[0] = a; } Bar foo(int i) { return m[i]; } void allFoo1() { auto fun = (int i) { return foo(i); }; auto r = map!(fun)([0]); } } void main() { Foo f = new Foo(Bar(1.5)); assert(f.m[0].m[0] == 1.5); f.allFoo1(); } If you replace the float with int, or if you use a dynamic array inside Bar (using an append inside Bar constructor) the error goes away. This is a situation where a stack trace is very useful. Bye, bearophile
Oct 03 2010
Ok, so with the test case sorted, how am I supposed to return the map over member function calls?
Oct 03 2010









Peter Alexander <peter.alexander.au gmail.com> 