How can I re-use a function?
Okay lets say I have this "main" function below:
bool A = false;
bool B = true;
void MainFunction(bool Whatever) {
if(!Whatever) {
A = true;
if(A) {
B = false;
} else if(!A) {
B = true;
}
}
}
Now I want to make a new function using the MainFunction, something like this:
MainFunction ANewFunction(false);
MainFunction AnotherNewFunction(true);
Obviously that won't work, so is there any way to "re-use" a function as a different function?
You're welcome to have one function call another. For example:
void ANewFunction() {
MainFunction(false);
}
void AnotherNewFunction() {
MainFunction(true);
}
You can even get fancy:
#include <functional>
auto ANewFunction = std::bind(&MainFunction, false);
auto AnotherNewFunction = std::bind(&MainFunction, true);
Either way, you can call ANewFunction or AnotherNewFunction, and MainFunction will get called with the given argument. (In the latter case, they're not really functions anymore. They're called function objects, or functors, but you cal still call them just like ordinary functions: ANewFunction().)
You can't "re-use" functions, at least not in the way I understand your question.
But you can create a new function that calls the original function and then does some additional work of its own. For example:
void PrevFunction(int one)
{
int i = one;
// do whatever
}
void NewFunction(int one)
{
PrevFunction(one);
// do new stuff
// ...
}
You could also define a class, and then use inheritance and virtual functions to modify the behavior of a particular set of functions from the base class.
typedef int (*function_t)(int); // new type - defines function type - address of function
// your function, PrevFunction is simply variable holding address of the function:
int PrevFunction(int one) { return one; }
// new variable of type function_t initialized by PrevFunction address:
function_t NewFunction = PrevFunction;
//And finally we can use either PrevFunction or NewFunction - they point to the same function body:
int a = PrevFunction(1); // a == 1
int b = NewFunction(2); // a == 2
Simply call MainFunction from your other function?
void ANewFunction()
{
MainFunction(false);
}
void AnotherNewFunction()
{
MainFunction(true);
}
If your question is how do you make AnotherNewFunction refer to a different A and B than ANewFunction, the answer is you can't, at least not without help from MainFunction. You can, however, update MainFunction:
void MainFunction(bool Whatever, bool& A, bool& B) {
if(!Whatever) {
A = true;
if(A) {
B = false;
} else if(!A) {
B = true;
}
}
}
bool A1 = false;
bool B1 = true;
void ANewFunction()
{
MainFunction(false, A1, B1);
}
bool A2 = false;
bool B2 = true;
void AnotherNewFunction()
{
MainFunction(true, A2, B2);
}
Another new-fangled solution, using lambda's:
auto ANewFunction = [](){ MainFunction(false); }
auto AnotherNewFunction = [](){ MainFunction(true); }
Related
This question already has answers here:
Function pointer to member function
(8 answers)
Closed 10 months ago.
I have an istance of a class A, that has some methods like:
class A
{
...
public:
bool DoOperation_one(Mytype* pSomeValue);
bool DoOperation_two(Mytype* pSomeValue);
...
bool DoOperation_th(Mytype* pSomeValue);
...
}
Another class, class B, has a pointer to A class and a method BMethod.
Class B
{
...
A* myPtrA;
...
bool BMethod(...); // arguments have to be defined
}
Is it possible to pass to BMethod, methods of A class instance as argument? I will try to be more clear with the follow pseudocode. In same place in class B i call BMethod with myPtrA method as argument (with parameters). I don't want to execute the myPtrA->DoOperation_two(somevalue) at calling time, but only in the BMethod (if statement):
...
bool bVal = BMethod(myPtrA->DoOperation_two(somevalue))
...
bool B::BMethod("valid signature" myFunction)
{
bool bfun=false;
if (myFunction)
{
do_something....
}
return bfun;
}
My goal is to call BMethod argument (DoOperation_one, DoOperation_two or DoOperation_th) in the body of BMethod only. I have been used template, but DoOperation_XXX is executed at calling time.
....
bool bVal = BMethod(myPtrA->DoOperation_two(somevalue));
or
bool bVal = BMethod(myPtrA->DoOperation_one(somevalue));
...
template <typename FunctionT>
bool BMethod(FunctionT myFunc)
{
bool bfun=false;
bool breturn = false;
while (!bfun)
{
if (myFunc)
{
bfun=true;
breturn = some_other_operation();
}
}
return breturn ;
}
Moreover, myFunc contains result of myPtrA->DoOperation_one(somevalue), and doesn't change in the while statement because it has executed at calling time.
Is there any other approach/solution?
You can pass a member function pointer but then you'll need an A instance to call it and a Mytype* to be passed as parameter:
struct Mytype {};
struct A {
bool DoOperation_one(Mytype* pSomeValue) { return true;}
bool DoOperation_two(Mytype* pSomeValue) { return true;}
bool DoOperation_th(Mytype* pSomeValue) { return true; }
};
struct B {
A a;
template <typename F>
bool BMethod(F f,Mytype* mt) {
bool bfun=false;
bool breturn = false;
while (!bfun) {
if ((a.*f)(mt))
{
bfun=true;
breturn = true;//some_other_operation();
}
}
return breturn ;
}
};
int main() {
Mytype mt;
B b;
b.BMethod(&A::DoOperation_one,&mt);
}
Instead of making BMethod a template, I could have spelled out the type explcitly, it is bool (A::*)(Mytype*). The syntax to call a member function pointer is a little clunky. If a is a pointer to A (like in your code) then it is (a.->f)(mt).
Note that this only makes sense if the value returned from A::DoOperation_xyz changes while B::BMethod is executing. For example when multiple threads are involved. If thats the case you need to be careful with synchronizing access to shared data to avoid data races. If this isnt multi-threaded, I see no reason to make it complicated and BMethod can simply be bool BMethod(bool x).
Im using C++ to create a timer. Ive look up the internet but not find anything that i can understand.Here is my code:
struct Timer{
bool timerRunning;
int time;
void Timer_Service(void* param){
timerRunning = true;
time = 0;
while(timerRunning){
wait(10);
time += 10;
}
}
void startTimer(){
Timer_Service((void*)"PROS");
pros::Task timerservice(Timer_Service,(void*)"PROS");// <- error here "reference to non-static member function must be called"
}
void stopTimer(){
timerRunning = false;
}
int getTime(){
return time;
}
};
How do i solve this error?
BTW pros::Task timerservice(Timer_Service,(void*)"PROS"); is a function that initializes a multitask loop.
Thanks all for your kind help.
The pros::Task constructor takes a function pointer.
Function pointers and pointers-to-member-functions are not the same thing.
You will have to pass a pointer to a non-member function (or a static member), ideally a forwarding delegate. You can create a class that contains a Timer_Service*, and pass it through the void* argument. In fact, in this case, since you only need to pass the object pointer, there's no need for a wrapping class.
struct Timer
{
bool timerRunning;
int time;
static void Timer_Service_Delegate(void* param) {
Timer* ptr = reinterpret_cast<Timer*>(param);
ptr->Timer_Service();
}
void Timer_Service() {
timerRunning = true;
time = 0;
while(timerRunning){
wait(10);
time += 10;
}
}
void startTimer() {
pros::Task timerservice(
Timer_Service_Delegate,
reinterpret_cast<void*>(this)
);
}
void stopTimer() {
timerRunning = false;
}
int getTime() {
return time;
}
};
I suspect you'll also need to keep the pros::Task in scope, but I don't know enough about the library to train you on that. Refer to its documentation.
I'm trying to modify a bool field in a method. The method accepts a pointer pointer bool, but can't seem to figure it out how to do this correctly.
This is a basic example of something similar I want to do:
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(&seenWarningA)
}
void pushWarning(bool ** warning) {
**warning = true;
}
}
This code example errors (sending bool* but needs to be bool**) and I've tried other ways with no luck. Can't find any online examples but maybe I'm searching for the wrong terms. What is the right way to do this?
Since you have a class, no parameters are required.
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning()
}
void pushWarning() {
seenWarningA = true;
}
}
Using references rather than pointers is more elegant.
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(seenWarningA)
}
void pushWarning(bool & warning) {
warning = true;
}
}
If you want to use pointers, the & operator just gives single pointer rather than a double point:
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(&seenWarningA)
}
void pushWarning(bool * warning) {
*warning = true;
}
}
You appear to be trying to pass an argument of bool* into a function that takes bool**. Remove one of the layers of indirection from the parameter list, or add one to the value you're passing in. Either should work.
Two mistakes:
First- your declaration of pushWarning is with parameter of type bool**, and you are trying to send bool*.
Second- you can simply use reference:
using namespace std;
class WarningManager {
public:
bool seenWarningA;
void updateWarnings() {
pushWarning(seenWarningA);
}
void pushWarning(bool &warning) { // You can simply use refference instead of pointer to pointer, or pointer at all..
warning = true;
}
};
int main()
{
WarningManager w;
w.seenWarningA = false;
w.updateWarnings();
cout << w.seenWarningA; // Prints 1
return 0;
}
I am trying to create a dynamic function pointer that points to some methods all the methods I want to save on the array return a bool and have an uint32_t parameter. The functions are Service functions. These are intended to be dynamic, so when a class is started, the constructor links the service function from the object to be called from outside the object.
With the code below I am getting the following error:
Build error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.
I have no clue what to do to overcome this problem, any idea would be greatly appreciated, thanks!
//File 1
typedef bool (*ServiceFunctionsType)(uint32_t);
//File 2
#include "File1.hpp"
extern uint8_t ServiceFunctions_size;
extern ServiceFunctionsType *ServiceFunctions;
void Service_Functions_Setup();
bool SetPtr(ServiceFunctionsType a);
void ClearPtr(uint8_t id);
//File 3
#include "File1.hpp"
ServiceFunctionsType *ServiceFunctions;
uint8_t ServiceFunctions_size = 0;
//File 4
#include "File2.hpp"
#include <stdlib.h>
void Service_Functions_Setup()
{
ServiceFunctions = NULL;
if(SERVICE_FUNCTION_POINTER_START_SIZE != 0)
{
ServiceFunctions_size = SERVICE_FUNCTION_POINTER_START_SIZE;
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType)*SERVICE_FUNCTION_POINTER_START_SIZE);
for(uint8_t i = 0; i < SERVICE_FUNCTION_POINTER_START_SIZE; i++)
{
ServiceFunctions[i] = NULL;
}
}
}
uint8_t SetServiceFunctionPointer(ServiceFunctionsType a, bool _realloc)
{
if( ServiceFunctions == NULL )
{
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType));
ServiceFunctions[0] = a;
return 0;
}
for(uint8_t i = 0; i < ServiceFunctions_size; i++)
{
if( ServiceFunctions[i] == NULL )
{
ServiceFunctions[i] = a;
return i;
}
}
if(_realloc)
{
ServiceFunctions_size++;
ServiceFunctions = (ServiceFunctionsType*)realloc(ServiceFunctions,sizeof(ServiceFunctionsType)*ServiceFunctions_size);
ServiceFunctions[ServiceFunctions_size - 1] = a;
return ServiceFunctions_size - 1;
}
return INVALID_SERVICE_FUNCTION_POINTER;
}
void ClearServiceFunctionPointer(uint8_t id)
{
ServiceFunctions[id] = NULL;
}
//File 5
class MonoStepSequencer
{
public:
MonoStepSequencer();
~MonoStepSequencer();
uint8_t ServicePointerID;
bool Service(uint32_t time);
private:
};
//File 6
#include "File2.hpp"
MonoStepSequencer::MonoStepSequencer()
{
ServicePointerID = SetServiceFunctionPointer(&this -> Service);
}
//This is the function to be called with a pointer
bool MonoStepSequencer::Service(uint32_t time)
{
//Some Code
}
You can try, to use lambdas. Create method like
std::function<void()> getService()
Where inside you can use:
return [this](){
Service();
};
Also if your methods should use arguments, you can use this method, but add arguments into return value and lambda.
One more, you can create lambda outside of class methods, like:
[&object]()
{
object.Service();
}
In this way, better to use std::shared_ptr to guŠ°rantee that object exists, when lambda called.
this -> Service is an unqualified or parenthesized non-static member function
You probably meant :: instead of -> Also, you need a type on the left, not a variable.
Also, please don't put spaces around ->. That makes it look like you're specifying a trailing return type or something.
I'm busy with making a leveleditor class in an engine but I'm stuck at passing a member function as parameter of another member function.
First I've made a typedef
typedef void (LevelEditor::*CallFunctionPtr)();
Then I have made a member function to check if the user clicks with his mouse on a hitregion. If so, another function needs to be called. So I've my first member function with 2 parameters
LevelEditor.h
void CheckClickCollision(HitRegion* region, CallFunctionPtr callFunctionPtr);
LevelEditor.cpp
void LevelEditor::CheckClickCollision( HitRegion* region, CallFunctionPtr callFunctionPtr)
{
if(GAME_ENGINE->GetLButtonMouseState())
{
if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
(this->*callFunction)();
m_bIsLeftPressed = true;
}
else
m_bIsLeftPressed = false;
}
Then I've two stupid example member functions:
LevelEditor.h
void LevelUp();
void LevelDown();
LevelEditor.cpp
void LevelEditor::LevelUp()
{
++m_iCurrentLevel;
}
void LevelEditor::LevelDown()
{
if(m_iCurrentLevel > 0)
--m_iCurrentLevel;
else
return;
}
And now I want to call that function every tick to check if there is a hit. So in my tick function:
CheckClickCollision(m_LeftArrowRegionPtr, LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, LevelUp);
And here I get the error on LevelDown and Levelup:
Error: argument of type void (LevelEditor::*)()" is incompatible with parameter of type "CallFunctionPtr *"
Dont know how to fix it. Tried different things, nothing worked
Try
CheckClickCollision(m_LeftArrowRegionPtr, &LevelEditor::LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, &LevelEditor::LevelUp);
For your convenience, here's the working sample (the compiler is GCC 4.7):
#include <stdio.h>
class LevelEditor;
typedef void (LevelEditor::*CallFunctionPtr)();
class LevelEditor
{
public:
LevelEditor() {}
void CheckClickCollision(void* region, CallFunctionPtr callFunction)
{
(this->*callFunction)();
}
void LevelUp() { printf("up\n"); }
void LevelDown() { printf("down\n"); }
void Test()
{
CheckClickCollision(NULL, &LevelEditor::LevelDown);
CheckClickCollision(NULL, &LevelEditor::LevelUp);
}
};
int main()
{
LevelEditor e;
e.Test();
return 0;
}
The other way to call this:
void Test()
{
CallFunctionPtr p;
p = &LevelEditor::LevelDown;
CheckClickCollision(NULL, p);
p = &LevelEditor::LevelUp;
CheckClickCollision(NULL, p);
}
You need to use std::function and std::bind, or lambdas if you have a supporting compiler.
void LevelEditor::CheckClickCollision( HitRegion* region, std::function<void()> callFunction)
{
if(GAME_ENGINE->GetLButtonMouseState())
{
if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
callFunction();
m_bIsLeftPressed = true;
}
else
m_bIsLeftPressed = false;
}
void Test()
{
// lambda
CheckClickCollision(NULL, [this] { LevelDown(); });
// bind
CheckClickCollision(NULL, std::bind(&LevelEditor::LevelDown, this));
}