This might sound a little convoluted, but here we go.
So, I have the following code:
void Utility::validateRangeAndModify(Pet pet, int checkint,
int numbertovalidate,
bool greaterorless)
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
pet.getAttributes()->func(100);
}
Firstly, This code is designed to validate a single integer. That part is easy.
Then, what I want it to do is carry out a function depending on if the integer meets the condition or not. In this case, setPetHunger() is being set to either 0 or 100. The issue is, I have setPetHealth(), and setPetEnergy() too.
The function I want it to perform is the thing that I want to change.
For instance. This code will only work for my pets Hunger. It won't work for it's Health, Happiness, or any of it's other variables. and I have a ton of other variables.
I'm wondering if there is any way to achieve something like this:
void Utility::validateRangeAndModify(Pet pet,
int checkint,
int numbertovalidate,
bool greaterorless,
string functiontouse)
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
pet.getAttributes()->FUNCTION_TO_USE(100);
}
I could use something like reflection for this in C#. However, I don't know an alternative function in c++
You can do it by passing the correct member function pointer as parameter to Utility::validateRangeAndModify as below:
void
Utility::validateRangeAndModify(Pet &pet, int checkint, int numbertovalidate,
bool greaterorless, void(Attrib::*memfun)(int)) {
^^^^^^^^^^^^^^^^^^^^^^^^^^
if(greaterorless) {
if(numbertovalidate < checkint) (pet.getAttributes()->*memfun)(0);
} else {
if(numbertovalidate < checkint) (pet.getAttributes()->*memfun)(100);
}
}
And then call it as (if Utility::validateRangeAndModify is not static use obj.validateRangeAndModify):
Utility::validateRangeAndModify(p, 10, 9, false, &Attrib::setPetHunger);
Utility::validateRangeAndModify(p, 10, 9, false, &Attrib::setPetThirst);
LIVE DEMO
You should use a function pointer:
void Utility::validateRangeAndModify(Pet pet, int checkint,
int numbertovalidate,
bool greaterorless,
void (*func)(int, attribs &))
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
func(100, pet.getAttribs());
}
You and the client will agree on the prototype of the function that you will pass; in this case, the prototype will be void func(int, attribs &);
The client can write code like this:
void happiness(int level, attribs &a)
{
// some code here
}
Utility::validateRangeAndModify(..., happiness);
Now happiness willl be called by your validateRangeAndModify function.
NOTE: happiness is a free function. If it is a member function, mark it as static: then there won't be the extra this argument.
To keep this simple, I'm providing a really trivial program that uses std::bind, std::function, and std::placeholders to allow calls to a bound method. This keeps the correct this with the method and generally prevents nastiness.
#include <iostream>
#include <functional>
// bait class to catch bound function calls. Replace this with pet for OP's example
class TwoMethods
{
public:
void method1(int val)
{
std::cout << "Method 1 received " << val << std::endl;
}
void method2(int val)
{
std::cout << "Method 2 received " << val << std::endl;
}
};
// utility function that will operate on a bound function
void utilityfunction(std::function<void(int)> func)
{
// calls passed function. Quietly handles bound this parameter and replaces
// placeholder with 42
func(42);
}
int main()
{
TwoMethods obj;
// call utility function with appropriate object and method
// the std::placeholders::_1 lets the compiler know there is another parameter that
// will be supplied later
utilityfunction(std::bind(&TwoMethods::method1, obj, std::placeholders::_1));
utilityfunction(std::bind(&TwoMethods::method2, obj, std::placeholders::_1));
}
In OP's case:
void Utility::validateRangeAndModify(int checkint,
int numbertovalidate,
bool greaterorless,
std::function<void(int)> func)
{
switch (greaterorless)
{
case 0:
{
if (numbertovalidate < checkint)
{
func(0);
}
}
break;
case 1:
{
if (numbertovalidate > checkint)
{
func(100);
}
break;
}
}
}
And called something like:
validateRangeAndModify(42, 666, false,
std::bind(&Attributes::setPetHunger,
pet.getAttributes(),
std::placeholders::_1))
Related
Well, all I want to do is a "switch" with a function pointer, but with methods pointers. The switch is that if I call the method Run(), it will either redirect to A::RunOn() or A::RunOff() according to Run ptr is pointing to these member functions.
I know it can be done. I did it in plain c but I have searched and googled to do the same thing in c++ but no luck.
class A
{
typedef (void)(A::*RunPtr)(int);
RunPtr RunMethod;
public:
RunMethod Run;
A()
{
Run = RunOff;
}
void SetOn(bool value)
{
if (value)
Run = RunOn;
else
Run = RunOff;
}
void RunOn(int)
{
// RunOn stuff here
}
void RunOff(int)
{
// RunOff stuff here
}
};
So I can call Run() and there will be a switch between the function calls, which I think is more efficient than just doing:
if (on)
RunOn();
else
RunOff();
Don't know how to do it!
Your member function pointer typedef is wrong (Despite the other issues in the shown code). You need
typedef void(A::*RunPtr)(int);
Or you can provide the alias for the member function pointer of class A with the help of using keyword as follows:
using RunPtr = void(A::*)(int);
RunPtr RunMethod;
Now in the SetOn you can do member pointer assignment as follows
void SetOn(bool value)
{
RunMethod = value ? &A::RunOn : &A::RunOff;
}
Now, in order to call the stored member function pointer, you may/ can provide a Run member function as follows:
void Run(int arg)
{
std::invoke(RunMethod, this, arg);
// do something...
}
The call to member function is a bit tricky.
However, this can be done using more generic std::invoke from <functional> header (Since c++17).
Here is the complete example:
#include <iostream>
#include <functional> // std::invoke
class A
{
using RunPtr = void(A::*)(int);
// or with typedef
// typedef void(A::*RunPtr)(int);
RunPtr RunMethod;
public:
void SetOn(bool value)
{
RunMethod = value ? &A::RunOn : &A::RunOff;
}
void Run(int arg)
{
std::invoke(RunMethod, this, arg);
// do something...
}
void RunOn(int arg) { std::cout << "RunOn: " << arg << "\n"; }
void RunOff(int arg) { std::cout << "RunOff: " << arg << "\n"; }
};
int main()
{
A obj;
obj.SetOn(true);
obj.Run(1); // prints: RunOn: 1
obj.SetOn(false);
obj.Run(0); // prints: RunOff: 0
}
(See a Demo)
Your code works fine once you fix the syntax mistakes in it, namely:
Class needs to be class.
in RunMethod Run;, RunMethod is not a type, it is a member variable. You meant to use RunPtr Run; instead (and get rid of RunMethod), but that won't work so well for you (see further below for why).
in Run = RunOn; and Run = RunOff;, you need to fully qualify the method name, and prefix it with the & operator, eg Run = &A::RunOn;.
Try the following:
class A {
public:
typedef void (A::*RunPtr)(int);
RunPtr Run;
A()
{
Run = &A::RunOff;
}
void SetOn(bool value)
{
if (value)
Run = &A::RunOn;
else
Run = &A::RunOff;
}
void RunOn(int param)
{
//RunOn stuff here
}
void RunOff(int param)
{
//RunOff stuff here
}
};
Note, however, that even though you can use Run as a public method pointer like this, the caller will still need to use operator.* or operator->* to actually call it, and that would not look so nice, eg:
A a;
(a.*a.Run)(...);
Online Demo
If you want to be able to call Run() like a.Run(...) then you have to make Run() be a standard method, and have it use a method pointer internally, eg:
class A {
typedef void (A::*RunPtr)(int);
RunPtr RunMethod;
public:
A()
{
RunMethod = &A::RunOff;
}
void SetOn(bool value)
{
if (value)
RunMethod = &A::RunOn;
else
RunMethod = &A::RunOff;
}
void RunOn(int param)
{
//RunOn stuff here
cout << "RunOn: " << param << endl;
}
void RunOff(int param)
{
//RunOff stuff here
cout << "RunOff: " << param << endl;
}
void Run(int param)
{
(this->*RunMethod)(param);
}
};
A a;
a.Run(...);
Online Demo
I have a class with a function that takes a std::function and stores it. This part seems to compile ok (but please point out any issue if there are any)
#include <functional>
#include <iostream>
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = std::bind(callback, std::placeholders::_1);
callback("hello world\n");
}
};
// pretty boring class - a cut down of my actual class
struct helper
{
worker the_worker;
bool work_callback(std::string str)
{
std::cout << str << std::endl;
return true;
}
};
int main()
{
helper the_helper;
//the_helper.the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1)); // <---- SEGFAULT (but works in minimal example)
the_helper.the_worker.do_work(std::bind(&helper::work_callback, &the_helper, std::placeholders::_1)); // <---- SEEMS TO WORK
}
I get a segfault, but I am not sure why. I have used this before, in fact, I copied this example from another place I used it. The only real difference that the member function was part of the class I called it from (i.e. this instead of the_helper).
So this is why I am also asking if there is anything else I am doing wrong in general? Like should I be passing the std::function as:
void do_work(std::function<bool(std::string)>&& callback)
or
void do_work(std::function<bool(std::string)>& callback)
As also noted by #Rakete1111 in comments, the problem probably was in this code:
bool work_callback(std::string str)
{
std::cout << str << std::endl;
}
In C++ if a non-void function does not return a value the result is undefined behavior.
This example will crash with clang but pass with gcc.
If helper::work_callback returns (e.g, true) the code works just fine.
I don't know why your code seg faults because I was spoiled and skipped std::bind straight to lambdas. Since you use C++11 you should really convert your code from std::bind to lambdas:
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = callback;
callback("hello world\n");
}
};
Now with work_callback and calling do_work things need some analysis.
First version:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([&](std::string s) { return the_helper.work_callback(s); });
}
Now this version works with your toy example. However out in the wild you need to be careful. The lambda passed to do_work and then stored in the_worker captures the_helper by reference. This means that this code is valid only if the helper object passed as reference to the lambda outlives the worker object that stores the m_callback. In your example the worker object is a sub-object of the the helper class so this is true. However if in your real example this is not the case or you cannot prove this, then you need to capture by value.
First attempt to capture by value (does not compile):
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
This does not compile because the copy of the_helper stored in the lambda object is const by default and as such you cannot call work_callback on it.
A questionable solution if you can't make work_callback const is to make the lambda mutable:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) mutable { return the_helper.work_callback(s); });
}
But you need to think if this is what you intended.
What would make more sense is to make work_callback const:
struct helper
{
worker the_worker;
bool work_callback(std::string) const
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
The reason for getting SEGFAULT has been already mentioned in the comments.
However, I would like to point out that, you need to use neither std::bind nor std::function, here in your given case. Instead, simply having a lambda and a function pointer you can handle what you intend to do.
struct worker
{
typedef bool(*fPtr)(const std::string&); // define fun ptr type
fPtr m_callback;
void do_work(const std::string& str)
{
// define a lambda
m_callback = [](const std::string& str)
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
};
bool flag = m_callback(str);// just call the lambda here
/* do some other stuff*/
}
};
struct helper
{
worker the_worker;
bool work_callback(const std::string& str)
{
std::cout << "Call from helper: ";
this->the_worker.do_work(str);
return true; ------------------------>// remmeber to keep the promise
}
};
And use case would be:
int main()
{
helper the_helper;
the_helper.work_callback(std::string("hello world"));
// or if you intend to use
the_helper.the_worker.do_work(std::string("hello world"));
return 0;
}
see Output here:
PS: In the above case, if worker does not required m_callback for later cases(i.e, only for do_work()), then you can remove this member, as lambdas can be created and called at same place where it has been declared.
struct worker
{
void do_work(const std::string& str)
{
bool flag = [](const std::string& str)->bool
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
}(str); -------------------------------------> // function call
/* do other stuff */
}
};
My question is rather simple, however i was unable to find anything about it on google (possibly because i am new to c++ and don't quite know the right terminology for everything yet). My question is, is it possible for me to add a reference to a function in a list, and if so, what is the correct way to do it?
Basically what i'm trying to do is to create an event class that would be able to store function references in a list so that i could do some basic event handling.
What im thinking of doing is something like this:
list<function> fnlist;
void add(function fn) {
fnlist.add(fn);
}
void call() {
for (function &fn: fnlist) {
fn();
}
}
Is something like this possible?
Please note that i would like to avoid using any event libraries if i could do this without any.
Absolutely, this is possible:
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
void quick() {
cout << "quick ";
}
void brown() {
cout << "brown ";
}
void fox() {
cout << "fox ";
}
int main() {
vector<function<void()> > events;
events.push_back(quick);
events.push_back(brown);
events.push_back(fox);
for (auto f : events) {
f();
}
return 0;
}
Use std::function<void()> to hold a functional object that encapsulates a callable that takes no parameters, and does not return a result.
Demo.
Use following :
/* ret_type : Return Type,
arg_type - type of argument (can be multiple, separated by comma)
*/
typedef std::function<ret_type( arg_type )> function ;
std::list < function> fnlist ;
void add(function fn)
{
fnlist.add(fn);
}
void call()
{
for (const auto &fn: fnlist)
{
fn();
}
}
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));
}
Suppose I have a class with 2 static functions:
class CommandHandler
{
public:
static void command_one(Item);
static void command_two(Item);
};
I have a DRY problem where I have 2 functions that have the exact same code for every single line, except for the function that it calls:
void CommandOne_User()
{
// some code A
CommandHandler::command_one(item);
// some code B
}
void CommandTwo_User()
{
// some code A
CommandHandler::command_two(item);
// some code B
}
I would like to remove duplication, and, ideally, do something like this:
void CommandOne_User()
{
Function func = CommandHandler::command_one();
Refactored_CommandUser(func);
}
void CommandTwo_User()
{
Function func = CommandHandler::command_one();
Refactored_CommandUser(func);
}
void Refactored_CommandUser(Function func)
{
// some code A
func(item);
}
I have access to Qt, but not Boost. Could someone help suggest a way on how I can refactor something like this?
You could use function pointers:
// type of the functions
typedef void Function(Item);
void CommandOne_User() {
// function pointer
Function *func = CommandHandler::command_one;
Refactored_CommandUser(func);
}
void CommandTwo_User() {
// can also be used directly, without a intermediate variable
Refactored_CommandUser(CommandHandler::command_two);
}
// taking a function pointer for the command that should be executed
void Refactored_CommandUser(Function *func) {
// calling the funcion (no explicit dereferencing needed, this conversion is
// done automatically)
func(item);
}
Besides the C way (passing a function pointer) or the C++ way mentioned by Jay here there is the other (modern) c++ way with boost or with a compiler with c++0x support:
void Refactored_CommandUser( boost::function<void (Item)> f ) {
// alternatively std::function with proper compiler support
}
With the advantage that this encapsulates a functor, and can be combined with boost::bind (or std::bind) to pass in not only free-function pointers that match the signature exactly, but also other things, like member pointers with an object:
struct test {
void f( Item );
};
void foo( Item i, std::string const & caller );
void bar( Item i );
int main() {
test t;
Refactored_CommandUser( boost::bind( &test::f, &t, _1 ) );
Refactored_CommandUser( boost::bind( foo, _1, "main" ) );
Refactored_CommandUser( bar ); // of course you can pass a function that matches directly
}
I posted a question very similar to this and this was the explanation I got:
Function Pointers
And here is the link to the question I posted: Function callers (callbacks) in C?
Another way to do this if you don't have access to tr1 or boost, is just to use function template. It's quite simple and obviously a C++ way.
Here's a compilable example similar to yours:
#include <iostream>
using namespace std;
class CommandHandler
{
public:
static void command_one(int i) { cout << "command_one " << i << endl; }
static void command_two(int i) { cout << "command_two " << i << endl; }
};
template <typename Func>
void CommandCaller(Func f)
{
f(1);
}
int main()
{
CommandCaller(&CommandHandler::command_one);
return 0;
}
I can think of two ways.
The C style way: pass the function to be called in as a function pointer.
The C++ way: create a base class that implements your code and replace the called function with a virtual method. Then derive two concrete classes from the base class, each one implementing the virtual function differently.
see this please
http://www.newty.de/fpt/fpt.html
Static member functions can be passed simply as function pointers.
Non-static can be passed as member-function pointer + this.
void Refactored_CommandUser(static void (*func)(Item))
{
// some code A
func(item);
// some code B
}
void CommandOne_User()
{
Refactored_CommandUser(&CommandHandler::command_one);
}
void CommandTwo_User()
{
Refactored_CommandUser(&CommandHandler::command_two);
}
So inspired by David Roriguez's answer, I tried it out on my own and, yup, it works:
Here's an example (stupid) code of the "modern" way to pass a function as a function parameter:
#include <functional>
#include <assert.h>
class Command
{
public:
static int getSeven(int number_)
{
return 7 + number_;
}
static int getEight(int number_)
{
return 8 - number_;
}
};
int func(std::tr1::function<int (int)> f, int const number_ )
{
int const new_number = number_ * 2;
int const mod_number = f(new_number);
return mod_number - 3;
}
int main()
{
assert( func(Command::getSeven, 5) == 14 );
assert( func(Command::getEight, 10) == -15 );
return 0;
}
I tried this on VS2008 with Intel C++ Compiler 11.1 with C++0X support on (don't know if C++0x support is really needed since it's in TR1).