Have a structure:
scheduled_call {
MyClass* object;
int value;
void (MyClass::*setter)(const int)
}
For class:
MyClass {
void doSomething(const int);
}
The structure compiles all well, but when I try to call the value as function, it throws error:
I need to execute call saved in this structure. I tried this:
void executeIt(scheduled_call cl) {
cl.object->*(cl.method)(cl.value);
}
But I get:
error C2064: term does not evaluate to a function taking 1 arguments
My coding is based on C/C++ function pointer guide. I'm doing this as an experiment, if it fails I can fallback to switch statement of course.
Can anybody compile this under Visual Studio 2010?
You need to provide a valid member function pointer definition in your struct:
scheduled_call {
MyClass* object;
int value;
void (MyClass::*method)(int); // <<<<
}
void MyClass::*method;
Is not a valid function pointer to a class memeber function. To get that we need
void (MyClass::*method)(int)
An now method is a pointer to function like MyClass::doSomething()
The problem was in method call. This is wrong:
cl.object->*(cl.method)(cl.value);
This is correct:
(cl.object->*cl.method)(cl.value);
Related
I'm trying to make a table of function pointers within a class. I haven't been able to find any examples of this online, most involve using member function pointers outside of their class.
for example:
class Test
{
typedef void (Test::*FunctionType)();
FunctionType table[0x100];
void TestFunc()
{
}
void FillTable()
{
for(int i = 0; i < 0x100; i++)
table[i] = &Test::TestFunc;
}
void Execute(int which)
{
table[which]();
}
}test;
Gives me the error "term does not evaluate to a function taking 0 arguments".
In this line in the Execute function:
table[which]();
You can't call it like that because it's not a normal function. You have to provide it with an object on which to operate, because it's a pointer to a member function, not a pointer to a function (there's a difference):
(this->*table[which])();
That will make the invoking object whichever object is pointed to by the this pointer (the one that's executing Execute).
Also, when posting errors, make sure to include the line on which the error occurs.
Seth has the right answer. Next time, look up the compiler error number on MSDN and you'll see the same: Compiler Error C2064.
You need a context in which to call your function. In your case, the context is this:
void Execute(int which)
{
(this->*table[which])();
}
I am trying to create a program which saves the function pointer of a member function to an array. The program then takes the function pointer from that array and calls the function said pointer points to. This works as long as the member function used does not have any arguments. When I give it arguments the following error occurs in Visual Studio 2017:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
My code is:
typedef uint8_t byte;
template<typename T>
class Test
{
public:
void FuncTest(byte* data)
{
cout << (T)(0.0625f) << endl;
}
};
typedef Test<float> fTest;
typedef Test<long long> lTest;
int main()
{
byte data[1024];
{
void (fTest::*ffp)(byte*) = &fTest::FuncTest;
//void (lTest::*lfp)(byte*) = &lTest::FuncTest;
printf("%p\n", ffp);
memcpy(&data[0], (int64*)&ffp, sizeof(int64));
}
{
int64 pData;
memcpy(&pData, &data[0], sizeof(int64));
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
printf("%p\n", pData);
func_pointer(nullptr);
}
}
If anyone could help, it would be greatly appreciated.
Ignoring the storage in an array your code is essentially:
void (Test::*ffp)(byte*) = &fTest::FuncTest;
void* pData = (void*)ffp;
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
func_pointer(nullptr);
The type of ffp is essentially (although not exactly due to differing calling conventions) void (fTest*, byte*) which doesn't match the type of func_pointer.
The solution to this is to use std::function with with either std::bind or lambdas to convert the function signatures. e.g.:
std::vector<std::function<void(byte*)>> functions;
fTest test;
functions.push_back([=](byte* data){ test.FuncTest(data); });
functions.front()(nullptr);
I have grouped several member functions into an array. How do I access a function from the array? I am getting 'error C2064: term does not evaluate to a function taking 0 arguments.' See below.
class A
{
public:
//Constructor
A()
{
//Fill function array
ClipFunction[0] = &A::ClipTop;
ClipFunction[1] = &A::ClipBottom;
ClipFunction[2] = &A::ClipLeft;
ClipFunction[3] = &A::ClipRight;
}
//Declare array
typedef void (A::*ClipFunction_ptr) ();
ClipFunction_ptr ClipFunction[4];
//Clipping functions
void ClipTop();
void ClipBottom();
void ClipLeft();
void ClipRight();
//Start clipping process
void StartClip();
};
//Define clipping functions
void A::ClipTop() {}
void A::ClipBottom() {}
void A::ClipLeft() {}
void A::ClipRight() {}
//Define A::StartClip()
void A::StartClip()
{
//Run through all functions in the array
for (unsigned int i = 0; i < 4; i++)
{
ClipFunction[i](); //ERROR. How do I access ClipFunction[i] ???
}
}
You need to dereference the function like this:
this->(*ClipFunction[i])();
What you're missing is the this or rather the compiler is complaining that it doesn't have the first parameter (the instance of the object invoking the member function) to pass it to the function.
To the compiler the member function:
void A::ClipFunction()
{
}
translates to something like:
void ClipFunction(A* this)
{
}
Hence the error complaining that the function is not one that takes zero arguments.
I think the problem is that you need use "this" explicitly as in http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/topic/com.ibm.xlcpp8l.doc/language/ref/cplr034.htm .
So in your case, you should use
(this ->* ClipFunction[i]) ();
instead of
ClipFunction[i]();
PS
When I reply this post, I didn't see Vite Falcon's answer. Basically we are saying the same thing but I don't think his code " this->(*ClipFunction[i])()" will compile because GCC gives errors on my machine. "(this->*ClipFunction[i])()" is the correct form.
I don't think you want the scope resolution operator :: in your typedef. Instead try putting
typedef void (*ClipFunction_ptr) ();
I would like to forward a callback to a function pointer. So I declare a static (int*) m_pointer1, as well as a method void RegisterCallback1( (int*)fct)
in class1.h:
public:
int RegisterCallback1( int (*fct) );
private:
static int (*m_Callback1);
in class1.cpp:
int class1::RegisterCallback1( int (*fct) )
{
m_Callback1= fct;
}
then, I want to forward the callback to the function pointer:
void class1::Callback1()
{
(*m_Callback1)();
}
But I get a compiler error "Expression must have (pointer-to)- function type
I have followed tutorial and read about function pointers and they seem to do it this way without any problems. Any ideas why?
EDIT:
So, I declare (int*)(void)m_Callback1 -Visual Studio requires a void there...-
Then how do I call the registerCallback function with the argument?
class1.RegisterCallBack1( ??? - class2::callback -??? );
static int (*m_Callback1) does not declate a function pointer, just a pointer to int: you forgot about the parameter list. You meant:
static int (*m_Callback1)();
and
int RegisterCallback1( int (*fct)() );
You haven't declared a function pointer, you've declared a normal data pointer. You are missing () at the end of the declaration.
You can try to limit the missing () errors pointed out by Oli and Dave by using a typedef for the callback function's signature: typedef int (*)() CallBack; This would at least have the merit of letting you think once about the precise number of brackets rather than at every point in your code where you use such a function.
I have a class Test with a peculiar data structure.
A member of class Test is a std::map where the key is a std::string and the mapped value is a struct defined as follows:
typedef struct {
void (Test::*f) (void) const;
} pmf_t;
Initialization of the map is OK. The problem is when I am trying to call the function pointed. I made up a toy example reproducing the problem. Here it is:
#include <iostream>
#include <map>
using namespace std;
class Test;
typedef void (Test::*F) (void) const;
typedef struct {
F f;
} pmf_t;
class Test
{
public:
Test () {
pmf_t pmf = {
&Test::Func
};
m["key"] = pmf;
}
void Func (void) const {
cout << "test" << endl;
}
void CallFunc (void) {
std::map<std::string, pmf_t>::iterator it = m.begin ();
((*it).second.*f) (); // offending line
}
std::map<std::string, pmf_t> m;
};
int main ()
{
Test t;
t.CallFunc ();
return 0;
}
Thanks in advance,
Jir
The name of the pmf_t type is f, so the first change is to remove the * to get second.f. That gives you a pointer-to-member value. To use a pointer-to-member, you need an instance. The only one you have available of the correct type is this, so use it with the ->* operator:
(this->*it->second.f)();
You need parentheses around the whole thing, or else the compiler thinks you're trying to call it->second.f() (which isn't allowed) and then applying the result to ->*.
The offending line is trying to call a member function without any object to call it on. If the intention is to call it for the this object, I believe the call should look like
( this->* ((*it).second.f) )();
Where this->* is the syntax for dereferencing a pointer-to-member for the current object. ((*it).second.f) is the pointer retrieved from the map, and () is the call operator for actually calling the function.
This is perhaps good as an exercise, but otherwise of limited use.
I think you might want to check out the C++ FAQ on this one. The syntax is apparently pretty tricky to get right (they actually recommend using a macro).
It might be too late for this question but, the seemingly complex synatax can be break down to two simple lines so it looks pretty clear:
void CallFunc (void)
{
pmf_t t = m["key"]; //1>get the data from key
(this->*t.f)(); //2>standard procedure to call pointer to member function
}
try this:
(this->*((*it).second.f)) ();