Thread overview
member function as template parameter workaround needed
Sep 13, 2012
timotheecour
Sep 13, 2012
bearophile
Sep 13, 2012
Andrej Mitrovic
Sep 14, 2012
timotheecour
Sep 14, 2012
Andrej Mitrovic
Sep 14, 2012
timotheecour
Sep 14, 2012
timotheecour
September 13, 2012
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
}
----
September 13, 2012
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
September 13, 2012
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);
}
September 14, 2012
> 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.
September 14, 2012
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/
September 14, 2012
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
}
----

September 14, 2012
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