Click here to Skip to main content
15,936,633 members
Please Sign up or sign in to vote.
3.33/5 (3 votes)
See more:
Hi.

I want to deduce the type of a member function passed as an argument to a function template.

I can deduce the types of the arguments of a member function when a pointer to the member function is passed as an argument to a function template, but not the member function type!

Anyone know how I can do this ?


// Deduction.h
#include<vector>


// Test Function
bool TestFun(int X)
{
	std::cout << "TestFun\n";
	return true;
};


// Test Component
struct ComponentB
{
	int Round(float X)
	{
		int x = (int)X;
		std::cout << "Round " << X << " = " << x << "\n";
		return x;
	}
};


// template type deduction from function arguments of function pointer
template<typename R, typename P1>
void Deduce( R(*pFunc)(P1) )
{
	// pFunc is a pointer to a function, but have we been able to deduce R and P1 ?
	R MyR;
	P1 MyParam1;

	MyR = pFunc(MyParam1);
	return;
};


// template type deduction from function arguments of member function pointer
template<typename R, typename T, typename P1>
void DeduceMFA( R(T::*pFunc)(P1) )
{
	// pFunc is a pointer to a Member function, but have we been able to deduce R, T and P1 ?
	R MyR;
	P1 MyParam1;
	T MyTarget;

	MyR = (MyTarget.*pFunc)(MyParam1);
	return;
};


// but we cannot use pFunc as a template argument for a templated type because it is a "local variable"!
template<typename R, typename T, typename P1>
void DeduceMFB( R(T::*pFunc)(P1) )
{
	// pFunc is a pointer to a Member function, but have we been able to deduce R, T and P1 ?
	R MyR;
	P1 MyParam1;
	T MyTarget;

	std::vector<pfunc> MyFuncts;	// Error pFunc is a local variable. Can't be used as template argument.

	MyR = (MyTarget.*pFunc)(MyParam1);
	return;
};


// so we implement it as a full template type
template<typename R, typename T, typename P1, typename R(T::*pFunc)(P1)>
void DeduceMFC( R(T::*pFunc)(P1) )
{
	// pFunc is a pointer to a Member function, but have we been able to deduce R, T and P1 AND  pFunc ?
	R MyR;
	P1 MyParam1;
	T MyTarget;

	MyR = (MyTarget.*pFunc)(MyParam1);
	return;
};


// code from main.cpp

// but then it cannot be deduced!!!

	Deduce( &TestFun );			// OK

	DeduceMFA( &ComponentB::Round );	// OK

	DeduceMFB( &ComponentB::Round );	// Error. 'pFunc' is not a valid template type argument for parameter '_Ty'

	DeduceMFC( &ComponentB::Round );	// Error. could not deduce template argument for 'pFunc'

Any help appreciated.

[edit] (by Stefan63) fixed the template headers (hope I got them right)[/edit]
Posted
Updated 23-May-11 5:53am
v8

I am slightly confused by these lines:
template<typename typename="" p1="">

As far as I am aware this is not valid C++, it could be part of new C++0x stuff as I haven't had time to review that in detail yet. But anyway you shouldn't require to use any new features to solve this problem so I will proceed anyway.

So firstly, to specify all the template arguments we need one typename for each and make them into a comma separated list. Notice the capitalisation on the P1 as the case must match your function prototype.
template<typename  R, typename T, typename P1>


Ok scratch that as I just noticed it seems that is a problem with the site.

Next lets look at that vector definition:
std::vector<pfunc> MyFuncts;

The reason it won't work is because as you say pfunc is a local variable, it is the argument passed to our function and template arguments must be types. It is simple to construct a type that matches the type of pfunc however using a our template arguments and a typedef. Which put together with the correct template specification gives us the following code:

template<typename  R, typename T, typename P1>
void DeduceMFB( R(T::*pFunc)(P1) )
{
    R MyR;
    P1 MyParam1;
    T MyTarget;

    typedef R (T::*pNowATypeFunc)(P1);
    std::vector<pNowATypeFunc> MyFuncts;

    MyR = (MyTarget.*pFunc)(MyParam1);
    return;
};


Now as I don't quite follow the template notation you have used I don't see much difference between the 3 DeduceMF functions well except for DeduceMFB including a vector, so I hope I didn't miss anything, but this function should work happily in all three cases. Hope that helps.
 
Share this answer
 
v3
Comments
Stefan_Lang 23-May-11 11:44am    
Ok scratch that as I just noticed it seems that is a problem with the site.
Yeah, this site has serious problems interpreting template syntax :(
The first error is simple: you used a variable as a template argument, but what you needed is the type of that variable. I'm not so familiar with function pointers, but the simplest solution will probably be to insert a typedef that defines the type of pfunc, and then use that typename as argument for your vector.

The second error I don't get: the code of DeduceMFC is an exact copy from DeduceMFA. The only difference is the template argument list, and TBH I have no idea what syntax that is.

Does your template argument list really look like this or was it messed up in formatting? If it's correct like it is, what does it mean?
[edit] fixed the template headers in the original post - I hope I got them right, but now there's no difference at all between DeduceMFB and DeduceMFC!?
[edit2] fixed the template arguments again to match the code posted in revision 1 - obviously the reformatting caused some inadvertent changes... [/edit2]
 
Share this answer
 
v3
Ok, I checked on Revision 1 of your question to see why there is supposed to be a difference between DeduceMFB and DeduceMFC. I've found, that unlike what is shown in the later revisions, the latter sports a fourth template parameter!

This fourth parameter however doesn't make any sense at all, and it is obvious why you get an error there.

I'm not quite sure what you meant to achieve with that fourth parameter. Maybe you can elaborate on that, so we can see what there is to it, and if it's even possible to sensibly incorporate this into the template?
 
Share this answer
 
Thanks for the help.

I have not made myself clear (or I completely misunderstand what I’m trying to do…?)

In DeduceMFB, I want to capture the actual member function pointer passed in (pFunc). I then wish to use this value? as a (non-type?) argument for another template’s parameter (vector is simply for example).

i.e I want to pass &ComponentB::Round.

I’m still not sure that I’m being clear….

What I’m trying to do in DeduceMFC is just take a wild stab that making it a template parameter it would somehow resolve to a real type (or real non-type!!!) that could be used to instantiate a templated type such as a vector.

I’ve really missed something haven’t I ?

....and what is it with the crazy symbols that didn't appear in the preview ?

Thanks again.
 
Share this answer
 
v3
Comments
Stefan_Lang 27-May-11 10:08am    
First:
Don't add your comments as solution
Second:
Don't mark your own comments as solution when they are not

As for your question:
Templates can only take types or constants as arguments, never the value of a variable! Remember, templates are generated at compile time! You passed variables as template arguments, and that is simply not possible.

P.S.: the 'crazy symbols' are most likely caused by the pasting settings. Check the various options below the 'Add solution' edit box. Unfortunately the use of these settings isn't always as clear as it could be - I had quite a lot of trouble to fix your code samples...

P.P.S.: The code that Charles posted above should work for your purposes.
WodgerDodger 27-May-11 16:50pm    
Thanks Stefan. Still getting used to driving the site.
Isn't "&ComponentB::Round" effectively a constant non-type value ?
I cant reconstitute the type with a typedef (pNowATypeFunc) as proposed in solution 2 below.
I don't need the member function type preserved, I need the member function pointer. Maybe the use of a std::vector was a bad example. Still working on it.
Cheers

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900