www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - member function as template parameter workaround needed

reply "timotheecour" <thelastmammoth gmail.com> writes:
As part of a larger system (which converts function parameters to 
a suitable type), I need to solve the following: pass a member 
function to a "run" template function, access its 
ParameterTypeTuple, and actually be able to run the function. 
I've simplified the problem (see below). Is there a way to pass a 
single argument to "run" ?
Both attempts 1 and 2 didn't compile. Attempt 3 compiles but is 
very bulky (need to pass 2 args).

Also I can't pass &a.fun2 as fun2 is not static.



----
class A{
	void fun2(double x){
		writeln("in fun2 with arg:",x);
	}
}
void run(alias fun,T...)(T args){
	writeln(typeid(ParameterTypeTuple!(fun)));
	fun(args);
}
void run2(alias fun,alias fun2,T...)(T args){
	writeln(typeid(ParameterTypeTuple!(fun)));
	fun2(args);
}
void test(){
	auto a=new A;

         //attempt#1
	//run!(a.fun2)(10);//compile error: Error: need 'this' to access 
member fun2

         //attempt#2
         //also tried to just pass x=>a.fun2(x), but then 
ParameterTypeTuple doesn't work with lambdas.


         //attempt#3
	run2!(a.fun2,x=>a.fun2(x))(10);//works but ugly
}
----
Sep 13 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
timotheecour:

         //attempt#2
         //also tried to just pass x=>a.fun2(x), but then 
 ParameterTypeTuple doesn't work with lambdas.

I think "x => a.fun2(x)" isn't an anonymous function, it's templated. Bye, bearophile
Sep 13 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/14/12, timotheecour <thelastmammoth gmail.com> wrote:
 Also I can't pass &a.fun2 as fun2 is not static.

Why not pass it as a runtime argument? void run(Fun, T...)(Fun fun, T args) { writeln(typeid(ParameterTypeTuple!(fun))); fun(args); } void test() { auto a = new A; run(&a.fun, 10); }
Sep 13 2012
prev sibling next sibling parent "timotheecour" <thelastmammoth gmail.com> writes:
 Why not pass it as a runtime argument?
 void run(Fun, T...)(Fun fun, T args)

Yes I actually ended up doing that however the behavior seems very buggy / unpredictable. It has issues when the class is defined in a different modules, but not always! Here's a very weird example: file main.d: ---- import fun; void run3(Fun,T...)(Fun fun,T args){ fun(args); } class A1{ void fun1(double x){ } double fun2(double x){ return x; } auto fun3(double x){ return x; } auto fun4(double x){ } } void main(){ test1; test2; } void test1(){ auto a=new A1; run3(&a.fun1,1); run3(&a.fun2,1); run3(&a.fun3,1); run3(&a.fun4,1); } void test2(){ auto a=new A2; run3(&a.fun1,1); run3(&a.fun2,1); run3(&a.fun3,1);//CT error run3(&a.fun4,1);//CT error } ----- file fun.d: ---- module fun; class A2{ void fun1(double x){ } double fun2(double x){ return x; } auto fun3(double x){ return x; } auto fun4(double x){ } } ---- There are other weird behaviors even without the auto statement, when dealing with templates defined outside. Please help or suggest alternatives! (esp in the case we don't want to edit said fun.d file.
Sep 13 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/14/12, timotheecour <thelastmammoth gmail.com> wrote:
 It has issues when the class is defined in a different modules,
 but not always!

This looks like a compiler bug. Feel free to file it in http://d.puremagic.com/issues/
Sep 13 2012
prev sibling next sibling parent "timotheecour" <thelastmammoth gmail.com> writes:
On Friday, 14 September 2012 at 00:31:15 UTC, Andrej Mitrovic 
wrote:
 On 9/14/12, timotheecour <thelastmammoth gmail.com> wrote:
 It has issues when the class is defined in a different modules,
 but not always!

This looks like a compiler bug. Feel free to file it in http://d.puremagic.com/issues/

I will. here's my other weird example, which I managed to simplify to as follows. Basically if: 1) the function is overloaded, and 2) it is a template, and 3) it is a member function (either static or nonstatic) Then you get a CT error that looks like: Error: (A).fun!(2) is not an lvalue That's a bug too right? (but different!) I wish delegates were more 1st class citizens and behaved... ---- void run(Fun)(Fun fun){ } class A { void fun1(int T)() if(T==2) { } void fun2(int T)() if(T==1) { } void fun2(int T)() if(T==2) { } void fun3(){} void fun3(int x){} void fun4(int T)() if(T==1) { } void fun4(int T)(int x) if(T==2) { } void fun5(T)() { } void fun5(T)(int x) { } static void fun6(int T)() if(T==1) { } static void fun6(int T)() if(T==2) { } } void fun7(int T)() if(T==1) { } void fun7(int T)() if(T==2) { } void main(){ auto a=new A; run(&a.fun1!2); //works //run(&a.fun2!2); //CT Error: a.fun2!(2) is not an lvalue run(&a.fun3); //works //run(&a.fun4!2); //CT Error: a.fun4!(2) is not an lvalue //run(&a.fun5!double); //CT Error: a.fun5!(double) is not an lvalue //run(&A.fun6!2); //CT Error: (A).fun6!(2) is not an lvalue run(&fun7!2); //works } ----
Sep 13 2012
prev sibling parent "timotheecour" <thelastmammoth gmail.com> writes:
I filed 2 bugs:

http://d.puremagic.com/issues/show_bug.cgi?id=8653 cannot take 
address of auto-return function declared in outside module: 
"Error: forward reference"

http://d.puremagic.com/issues/show_bug.cgi?id=8654 cannot take 
address of function which is 1)overloaded, 2) templated, and 3) 
member (static or not): Error: xxx is not an lvalue
Sep 13 2012