I want to have objects with one method which calls a function (but every object should have a different function to call). I will try to show you what I mean by showing an example:
class Human
{
public:
void setMyFunction(void func); // specify which function to call
void callMyFunction(); // Call the specified function
};
void Human::setMyFunction(void func) // ''
{
myFunction = func;
}
void Human::callMyFunction() // ''
{
myFunction();
}
void someRandomFunction() // A random function
{
// Some random code
}
int main()
{
Human Lisa; // Create Object
Lisa.setMyFunction(); // Set the function for that object
Lisa.callMyFunction(); // Call the function specified earlier
}
This code (obviously) doesn't work but I hope you understand what I am trying to accomplish.
MfG, TPRammus
You might use std::function.
#include <functional>
class Human
{
std::function<void()> mFunc;
public:
void setMyFunction(std::function<void()> func) { mFunc = func; }
void callMyFunction() { if (mFunc) mFunc(); }
};
Demo
I would suggest using a simple function pointer. Just do this:
class Human
{
public:
using func_t = void (*)();
void setMyFunction(func_t f) {
func = f;
}
void callMyFunction() {
func();
}
private:
func_t func;
};
The reasons why one might prefer function pointers to std::function are:
Performance. Calling std::function tends to be slower, than calling a function by pointer.
std::function needs truly ugly syntax when one needs to bind it to an overloaded function.
Example:
void foo();
void foo(int x = 0);
void check() {
Human h;
h.setMyFunction(&foo);
}
Will fail to compile.
Related
I am doing a small project using arduino and I need to use an array of methods.
I've tried doing what I would normally do in C# / Java but that didn't work. I went online and tried many different examples and I kept getting lead to the same error message.
class ColourSensor{
public:
void (*routine[3])() = {
routine0,
routine1,
routine2
};
void routine0();
void routine1();
void routine2();
};
When I compile I get the following error:
cannot convert 'ColourSensor::routine0' from type 'void (ColourSensor::)()' to type 'void (*)()'
Things get complicated because they are methods. A method has an implicit hidden this parameter, so it's a different type than a free functions.
This is the correct syntax:
class ColourSensor
{
public:
using Routine = void (ColourSensor::*)();
Routine routines[3] = {
&ColourSensor::routine0,
&ColourSensor::routine1,
&ColourSensor::routine2,
};
void routine0();
void routine1();
void routine2();
void test()
{
// calling syntax:
(this->*routines[0])();
}
};
An alternative which simplifies the calling syntax using non-capturing lambdas (which can decay to function pointer):
class ColourSensor
{
public:
using Routine = void (*)(ColourSensor*);
Routine routines[3] = {
[](ColourSensor* cs) { return cs->routine0(); },
[](ColourSensor* cs) { return cs->routine1(); },
[](ColourSensor* cs) { return cs->routine2(); }
};
void routine0();
void routine1();
void routine2();
void test()
{
// simpler calling syntax
routines[0](this);
}
};
Going one step further (and off the rails), if you know you always use this object to call the methods you need to capture this in lambda. The problem now is that capturing lambdas can't decay to function pointers and since every lambda is a different type you can't store them in an array. The usual solution in C++ is type erasure with std::function. Unfortunately arduino C++ environment doesn't have the C++ standard library (because of the size constraints). For reference, this is how it would have looked (and since we are using the standard library, we use std::array):
/// !! not working in Arduino !!
#include <functional>
#include <array>
class ColourSensor
{
public:
std::array<std::function<void(void)>, 3> routines = {
[this]() { return this->routine0(); },
[this]() { return this->routine1(); },
[this]() { return this->routine2(); }
};
void routine0();
void routine1();
void routine2();
void test()
{
// simple calling syntax
routines[0]();
}
};
There is a workaround for this. And although it's a bit of work to setup, it's actually faster than the std::function because we don't use type erasure:
class ColourSensor;
class Routine
{
private:
using R = void (ColourSensor::*)();
R routine_;
ColourSensor* calling_obj_;
public:
Routine(R routine, ColourSensor* calling_obj)
: routine_{routine}, calling_obj_{calling_obj}
{}
void operator()();
};
class ColourSensor
{
public:
Routine routines[3] = {
Routine{&ColourSensor::routine0, this},
Routine{&ColourSensor::routine1, this},
Routine{&ColourSensor::routine2, this}
};
void routine0();
void routine1();
void routine2();
void test()
{
// simple calling syntax
routines[0]();
}
};
void Routine::operator()() { return (calling_obj_->*routine_)(); }
If however your routines don't use the state of the ColourSensor, than you can make them static functions:
class ColourSensor
{
public:
using Routine = void (*)();
Routine routines[3] = {
routine0,
routine1,
routine2,
};
static void routine0();
static void routine1();
static void routine2();
void test()
{
routines[0]();
}
};
I am trying to write a program that will execute a function based on a string I fetch from a database.
Basically what I do is:
// Create an enum
enum AFunc{
invalidFunction,
function2,
function3
}
// have a class handling the functions
struct A
{
static AFunc resolveStringToFunction(std::string) {...}
template<int T>
void execute(...)
{
// this may not be called = invalidFunction
}
template<>
void execute<1> (...)
{
// do stuff = function1
}
template<>
void execute<2> (...)
{
// do stuff = function2
}
};
In my application i do this:
A a;
std::string funcString = getFromDatabase (...) // Not really, but this is abstract
const AFunc funcType = A::resolveStringToFunction(funcString);
a.execute<funcType>(...);
The problem here is that the compiler does not accept the dynamic calling of a template function, because (as I understood it) it needs to know which function is called by compile time.
Is there any way around this?
Is there a better solution to this problem? Maybe a design pattern?
namespace afunc // dont pollute global namespace
{
typedef std::function<void(...)> aFunc;
static function1(...)
{
// do stuff
}
static function2(...)
{
// do stuff
}
const std::unordered_map<std::string, aFunc> functions (
{{"function1", &function1},{"function2", &function2}} ); // afunc
And it is called by the following code:
std::string funcString = getFromDatabase (...) // Not really, but this is abstract
afunc::functions.at(funcString)(...) // at because the map is const, so it's even threadsafe
I want to do something like this:
struct CLI_Command{
CLI_Command(char* s, void (*h)(void)){
command_string = s;
handler = h;
}
char* command_string;
void (*handler)(void);
};
class CLI {
public:
CLI();
private:
CLI_Command cli_table[NO_CLI_COMMANDS] = {
CLI_Command("Command1", handler1),
CLI_Command("Command2", handler2)
};
void handler1(){};
void handler2(){};
};
I know that I need something similar to CLI::*handler, but I can't get the syntax right. I keep running into errors like this:
"error: no matching function for call to 'CLI_Command::CLI_Command(const char [4], <unresolved overloaded function type>)"
This illustrates the correct syntax:
class CLI;
struct CLI_Command
{
CLI_Command(char* s, void (CLI::*h)(void))
{
command_string = s;
handler = h;
}
char* command_string;
void (CLI::*handler)(void);
void raise( CLI* the_cli ) { return (the_cli->*handler)(); }
};
class CLI
{
public:
CLI();
private:
static CLI_Command cli_table[NO_CLI_COMMANDS];
void handler1(){};
void handler2(){};
};
CLI::CLI_Command cli_table[NO_CLI_COMMANDS] = {
{ "Command1", &CLI::handler1 },
{ "Command2", &CLI::handler2 }
};
Names of member functions do not decay to pointer-to-member. You must use & explicitly, and a qualified name, when creating a pointer-to-member.
In addition to other answers, another option is to use std::function together with std::bind():
struct CLI_Command{
...
std::function<void> handler;
};
class CLI {
...
CLI_Command cli_table[NO_CLI_COMMANDS] = {
{ "Command1", std::bind(&CLI::handler1, this) },
{ "Command2", std::bind(&CLI::handler2, this) }
};
void handler1(){};
void handler2(){};
};
void handler1(){}
void handler2(){}
are member functions of CLI. The correct way to "address to" them is &CLI::handler1 and not handler1. However then, they won't be accepted by void (*h)(void), which would need to be changed to void (CLI::*h)(void). But that is probably not what you want.
Maybe consider reading about std::function for type erasure, or make your handler1/handler2 static.
You should use the syntax for a pointer to class member instead of the syntax for a loose function pointer.
class CLI;
struct CLI_Command{
CLI_Command(char* s, void (CLI::*h)(void)){
command_string = s;
handler = h;
}
char* command_string;
void (CLI::*handler)(void);
};
In addition, make sure you call the function through the pointer of the current CLI class;
void CLI::process(char *cmd) {
CLI_Command command* = /* lookup the command */
this->(command->handle)();
}
To get it working, make your methods static
static void handler1(){};
static void handler2(){};
Whatever consequences (read here please, for more detailed info) this will have :-( .
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).