I create a QFuture that I want to use to parallelize calls to a member function. More precisely, I have a class solveParallel with .h :
class solverParallel {
public:
solverParallelData(Manager* mgr_);
virtual ~solverParallel(void);
void runCompute(solveModel * model_);
bool resultComput();
private:
Manager *myMgr;
QFuture<bool> myFutureCompute;
};
where the methode runCompute() is creating the myFutureCompute member. .cpp looks like
solveParallel::solveParallel(Manager* mgr_)
:m_mgr(mgr_)
{
}
solverParallel::~solverParallel(void){}
void solverParallel::runCompute(solveModel* model)
{
futureComput = QtConcurrent::run(&this->myMgr,&Manager::compute(model));
}
bool solverParallelData::resultComput()
{
return m_futureComput.result();
}
Include(s) are all right. Compilation fails, on line
futureComput = QtConcurrent::run(&this->myMgr,&Manager::compute(model));
with this error:
Error 44 error C2784: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(Param1),const Arg1 &)' : could not deduce template argument for 'T (__cdecl *) (Param1)' from 'Manager **' solverparallel.cpp 31
In addition, on mouse info for '&Manager' in same line of code stands: Error: a nonstatic member reference must be relative to a specific object.
Do you see where is the trick? Thanks and regards.
From the official documentation :
QtConcurrent::run() also accepts pointers to member functions. The
first argument must be either a const reference or a pointer to an
instance of the class. Passing by const reference is useful when
calling const member functions; passing by pointer is useful for
calling non-const member functions that modify the instance.
You are passing a pointer to a pointer. Also notice that you cannot pass the arguments the way you do, but as extra arguments in the run function. The following should work:
futureComput = QtConcurrent::run(this->myMgr,&Manager::compute, model);
Related
I want a function that can be called inside of another class which has a single input parameter of type void function pointer. Inside the function, the function pointer should execute the function to which it's pointing.
// inside TestClass.h
class TestClass
{
public:
template<class UserClass>
static void TestingFctPtrStatic(void (UserClass::* TestFunction)(void), UserClass* Object);
};
template<class UserClass>
inline void TestClass::TestingFctPtrStatic(void (UserClass::* TestFunction)(void), UserClass* Object)
{
Object->TestFunction();
}
Calling the function inside the constructor of TestClass like this gives me the following compile error:
// inside TestClass.cpp
TestClass::TestClass()
{
TestClass::TestingFctPtrStatic<TestClass>(&TestClass::PrintStuff, this);
}
With PrintStuff():
void TestClass::PrintStuff()
{
std::cout << "Printing stuff!" << std::endl;
}
error C2039: 'TestFunction': is not a member of 'TestClass'
message : see declaration of 'TestClass'
message : see reference to function template instantiation 'void TestClass::TestingFctPtrStatic(void (__cdecl TestClass::* )(void),UserClass *)' being compiled
with
[
UserClass=TestClass
]
Edit:
I fixed it by using more parentheses in the implementation:
template<class UserClass>
inline void TestClass::TestingFctPtrStatic(void (UserClass::* TestFunction)(void), UserClass* Object)
{
(Object->*TestFunction)();
}
void(UserClass::* TestFunction)(void)
This is not a pointer to a function. It is a pointer to a class method.
TestFunction();
You can't just call a class method out of thin air. You need an object, an instance of the class, whose method gets called. If p is a pointer to a UserClass, in other words:
UserClass *p=(points to somewhere);
then you would invoke its method using this syntax:
(p->*TestFunction)();
It is unclear from your question's description where the object whose method gets invoked comes from, so you need to figure it out, yourself, based on all the other information you have but was not included in the question. In some form or fashion you'll need to find a UserClass object, somewhere -- either passed in as an additional parameter, or it's lying around, somewhere, in the general vicinity -- and then you can use the TestFunction pointer to invoke this object's method.
This is fundamental to C++, provided that this is a class method. If this PrintStuff is a static class method, then this would be, indeed, a plain old function pointer:
void (*TestFunction)();
And it would get invoke, via a pointer, no differently than any other function.
Here is my Code:
I want to use a class inside my custom MyStateMachine. I do not want to inherit de StateMachine class as I just want to use it with its functions. The MyStateMachine class is only to encapsulate a few things.
MyStateMachine.h
#include <StateMachine.h>
class MyStateMachine {
public:
void Initialisation();
private:
StateMachine machine = StateMachine();
State* m0Initialisation = machine.addState(&Initialisation); // problem here
};
MyStateMachine.cpp
#include "MyStateMachine.h"
void MyStateMachine::Initialisation() {
// do initialisation stuff here
}
machine.addState expects a function pointer as argument:
State* addState(void (*functionPointer)());
I get the following error message:
error: no matching function for call to 'StateMachine::addState(void (MyStateMachine::*)())
note: State* StateMachine::addState(void (*)())
State* addState(void (*functionPointer)());
note: no known conversion for argument 1 from 'void (MyStateMachine::*)()' to 'void (*)()'
Compilation error: no matching function for call to 'StateMachine::addState(void (MyStateMachine::*)())'
If I define the function outside the class, I can successfully pass this function as a function pointer (&Initialization).
I guess it has something to do that it is a function of a class and it needs the reference to the object. But even with that I did not find a solution.
How could I pass the function? If possible without external libraries (e.g. std::bind).
I have looked at a few posts but could not find a proper solution.
pass-an-objects-member-function-as-argument-function-pointer
class-member-function-as-function-pointer
using-pointers-to-member-to-pass-member-function-as-arguments
There is some different solutions to your problem.
1: Change the type of your funciton pointer in Statemachine::addState(...) to be a function pointer to a member type instead of a function pointer to a non member function.
Check out section "Pointers to members" here
2: Use std::function as the type of addState and do
State* m0Initialisation = machine.addState([this]() {Initialisation(); });
3: Change Initialization to be static and send in a pointer to your class every time you call the function.
static void Initialisation(StateMachine &self);
The problem is that StateMachine::addState expects a normal function pointer, which is different from a member function pointer. You can make your Initialization function static. Then the member function pointer is essentially a normal function pointer:
struct State {};
struct StateMachine {
State* addState (void (*)()){ return nullptr; }
};
class MyStateMachine {
public:
static void Initialisation();
private:
StateMachine machine = StateMachine();
State* m0Initialisation = machine.addState(&Initialisation); // no problem here
};
Member functions always have an implicit first argument, which is a pointer or reference to an instance of the class. This is the main difference between a normal function pointer and a member function pointer. So taking the implicit argument into account, the member function is not a void nullary function with signature `void (*)(). Static member functions do not have an implicit first argument, so member function pointers to static member functions can be treated like normal function pointers.
I want to be able to use a member variable to hold the address a function to call
I got the error:
cannot convert 'void (TestClass::*)(bool)' to 'void (*)(bool)' in
assignment
TestClass.cpp
#include "TestClass.h"
TestClass::TestClass()
{
_myFctPtr = &setFired;
}
void TestClass::setFired(bool isFired)
{
_fired = isFired;
}
void TestClass::updateValue()
{
(_myFctPtr)(true);
}
bool TestClass::getFired()
{
return _fired;
}
TestClass.h
#pragma once
class TestClass
{
private:
bool _fired = false;
protected:
void (*_myFctPtr)(bool);
public:
TestClass();
void setFired(bool);
void updateValue();
bool getFired();
};
The error:
cannot convert 'void (TestClass::*)(bool)' to 'void (*)(bool)' in assignment
Is showing you that pointers to class member functions have a different type from regular function pointers. This is because, in addition to the regular function arguments and return type, these functions are differentiated by the object they are called on (i.e. their this), which must be provided when invoking them.
Specifically, for a pointer to a function on TestClass which accepts a bool argument as shown here, you need to to define your field as the type void (TestClass::*)(bool):
void (TestClass::*_myFctPtr)(bool);
You can call this like so, assuming you want to invoke the method on this:
((this).*(_myFctPtr))(true);
This article provides additional useful information and advice on better, cleaner ways to invoke pointers to member functions - e.g. using std::invoke for cleaner syntax than what I provided above - but this is the bare minimum to quickly solve your issue.
I have the following call:
void Derived::GetEntry(Skill&);
InorderTraverse(GetEntry);
Which calls
void Base<ItemType>::InorderTraverse(void Visit(ItemType&)) const
Attempting to compile as written generates
error C3867: 'Derived::GetEntry': function call missing argument list; use '&Derived::GetEntry' to create a pointer to member
Using &Derived::GetEntry generates
cannot convert parameter 1 from 'void (__thiscall Derived::* )(Skill &)' to 'void (__cdecl *)(ItemType &)'
Changing the declaration to static void GetEntry... fixes these problems, but creates a new set of problems (namely that I can't access non-static objects (nonstatic member reference must be relative to a specific object)
I have a similar traversal operation that works fine with a static declaration, since the called function just displays information about each object on which it is called.
I've been searching for a few days now for an answer, and I feel like it's something simple. Is there a way to use a nonstatic function as a parameter in another function call?
The complete code is: https://github.com/mindaika/SkillTree
Edit: Inserted full working example instead.
I suggest you use the std function pointers instead.
For instance:
#include <functional>
void main()
{
class TheClass
{
public:
TheClass()
{
m_function = ( std::tr1::bind(&TheClass::run, this) );
};
void run()
{
// stuff to do
};
std::tr1::function<void ()> m_function;
};
TheClass theclass;
theclass.m_function();
}
m_function (); // call function
As I mentioned in my question, I was trying to get around the "memory leak" caused by using a static variable (it's not actually a leak, since statics are destroyed, but not until after the leak detector runs). I ended up using a modification of the encapsulated pointer described here: C++ freeing static variables
I am trying to do multithreading by boost::bind. But, I got error:
src/model.cpp:225: instantiated from here
/boost_1_45_0v/include/boost/bind/mem_fn.hpp:333: error: pointer to member type void (Model::)(taskDataSPType&) incompatible with object type taskDataSPT1ype
make: * [model.o] Error 1
Here is my code:
void Model::runTask(taskDataSPType& myTask)
{}
taskDataSPType myTask;
fifo_pool tp(thread_num);
for (int i = 0 ; i < totalTaskNum ; +i)
{
taskQueue.wait_and_pop(myTask, i);
myTask.taskID = i ;
// run the typical iterations
tp.schedule(boost::bind(&Model::runTask, &myTask));
}
tp.wait();
In another header file, I have :
typedef struct taskDataSPT1ype taskDataSPType;
struct taskDataSPT1ype
{
int taskID;
int startNode;
int endNode;
};
Model::runTask is (presumably) a non-static member function. That means you cannot call it without an instance of the class. boost::bind knows this, and therefore it expects the first parameter to be a Model of some form, or a derived class thereof. So your bind takes two parameters: the Model and the function argument taskDataSPType&.
Also, your argument is a reference, but you seem to be attaching a pointer. That's not going to work either. You may need to use boost::ref, as follows:
tp.schedule(boost::bind(&Model::runTask, /*Some Model Instance*/,
boost::ref(myTask)));
&Model::runTask is a member function, and as such it has an extra implicit argument this. So in your particular case, you want to bind it with two arguments: an instance of Model and a taskDataSPType object. Note that if one wants to pass references with bind it has to use boost::ref or boost::cref.