I hope to use map library to call a function by a string with the function name, I've tested the following example and everything are working well.
#include <string>
#include <iostream>
using namespace std;
typedef void (*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &func1;//
}
void callFunc(const std::string& str)
{
(*strFuncMap[str])();
}
int main()
{
buildMap();
callFunc("func1");
return 0;
}
However, as I define all these things in a class, there is a compiler error occur:
#include <map>
#include <string>
#include <iostream>
using namespace std;
class theClass {
public:
typedef void (*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &func1;// a value of type cannot be assigned to an entity of type
}
void callFunc(const std::string& str)
{
(*strFuncMap[str])();
}
};
int main()
{
theClass a;
a.buildMap();
a.callFunc("func1");
return 0;
}
I've tried to solve this problem for a couple of hours. Or is there any other way to use string to call function in a class? I will very appreciate if someone can help me. THANKS!!
Your code doesn't work because func1 is a member function and the syntax for member functions is different.
You need a map of member function pointers (offsets)
typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;
Then you can store the pointer with
strFuncMap["func1"] = &theClass::func1;
And you need an object to call a member function
(this->*strFuncMap[str])();
The final code:
#include <map>
#include <string>
#include <iostream>
using namespace std;
class theClass {
public:
typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &theClass::func1;
}
void callFunc(const std::string& str)
{
(this->*strFuncMap[str])();
}
};
int main()
{
theClass a;
a.buildMap();
a.callFunc("func1");
return 0;
}
typedef void (*pFunc)();
This declares pFunc to be the type of function pointers. That is, the type of pointers to functions which exist at the top-level. This excludes member functions, lambda functions, and functors. Consider
using pFunc = std::function<void()>
Now your type will correctly accept anything that can reasonably be interpreted as a callable object. Note that member functions still need to be wrapped in a lambda, since you're closing around this.
strFuncMap["func1"] = [this]() { this->func1(); };
Related
In below code snippet while calling call back function "Invalid use of void expression" error
is flashed by the compiler.
#include <iostream>
#include <functional>
using namespace std;
template<class type>
class State {
public:
State(type type1,const std::function<void (type type1 )> Callback)
{
}
};
template <class type>
void Callback(type type1 )
{
//Based on type validation will be done here
}
int main()
{
State<int> obj(10,Callback(10));
return 0;
}
Just want to know what is the wrong here so that same can be addressed .
It seems that you want to pass the Callback<int> function itself, not its return value (which there is none), to the constructor of obj. So do just that:
State<int> obj(10, Callback<int>);
Your current code actually calls Callback(10) first and then tries to take its void "return value" to pass it to the constructor of obj. Passing void is not allowed in C++, which is why the compiler is complaining. (Callback(10) is the "void expresson" here.)
I guess this is what you want
#include <iostream>
#include <functional>
using namespace std;
template<class type>
class State {
public:
State(type type1,const std::function<void (type)> callback)
{
callback(type1);
}
};
template <class type>
void Callback(type type1 )
{
}
int main()
{
State<int> obj(10, Callback<int>);
return 0;
}
I would like to go with lambda expression approach to avoid the confusion :
#include <iostream>
#include <functional>
using namespace std;
template<class type>
class State
{
public:
State( type type1, const std::function<void (type type1 )> Callback)
{
Callback(type1);
}
};
int main()
{
State<int > monitor(10,[] ( int fault) {std::cout<<"Any Message"; });
return 0;
}
I try to implement Scott Mayer book code example, the example is about calling functor through function object
the header file gameCharachter.h
#ifndef GAMECHARACTER_H
#define GAMECHARACTER_H
#include <iostream>
#include <typeinfo>
using namespace std;
#include <tr1/functional>
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter
{
public:
typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{
}
~GameCharacter()
{
}
int healthValue() const
{
return healthFunc(*this);
}
private:
HealthCalcFunc healthFunc;
};
class EyeCandyCharacter: public GameCharacter // another character
{
public:
explicit EyeCandyCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: GameCharacter(hcf)
{
cout<<typeid(*this).name()<<"::"<<__FUNCTION__<<""<<endl;
}
};
struct HealthCalculator
{
/*explicit*/ HealthCalculator()
{
}
int operator()(const GameCharacter& gc) const // calculation function
{
cout<<typeid(*this).name()<<"::"<<__FUNCTION__<<""<<endl;
return 0;
}
};
#endif // GAMECHARACTER_H
the main.cpp is :
#include "gamecharacter.h"
int main()
{
EyeCandyCharacter ecc1(HealthCalculator());
ecc1.healthValue();
}
why function<> object refuse to call the operator() function in healthvalue()
EyeCandyCharacter ecc1(HealthCalculator());
declares a function called ecc1 that takes an argument of type "pointer to function taking no arguments and returning a HealthCalculator" and returns a EyeCandyCharacter. I assume that this isn't your intent.
this is the correct call , it should be called by bind
#include "gamecharacter.h"
int main()
{
HealthCalculator hc;
EyeCandyCharacter ecc1(std::tr1::bind(&HealthCalculator::operator(),hc,tr1::placeholders::_1));
ecc1.healthValue();
}
I want to have a class that can have a callback set to a pointer to member function. This means I need to store the address of the function, and the address of the object instance. The function should have the proper prototype and return value to what the callback expects.
I've played around with std::mem_fn and boost::bind (with the Boost Signals2 library), but it seems like I have to know the type of the class containing the callback function to store this information.
It seems like there should be a way to store a couple void* that would point to any object/function, but this obviously smells funny, loses type safety, etc.
Given a class SomeClass with a method some_method, I want to be able to do something like this:
SomeClass obj;
some_other_class.set_callback(&SomeClass::some_method, &obj);
Here is how I was able to accomplish this using Boost. Note that this uses Boost signals, and seems like overkill for a simple callback. Also, there is the issue of signals using "combiners" to determine the return value of the callback, since there are potentially multiple slots connected to a single signal. I only need support for a single callback. Also note that this is a complete compilable program:
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <string>
using namespace std;
struct MessageSource
{
boost::signals2::signal<void(const string &)> send_message;
typedef boost::signals2::signal<void(const string &)>::slot_type slot_type;
template<typename A, typename B>
boost::signals2::connection connect(A a, B b)
{
return send_message.connect(boost::bind(a, b, _1));
}
void send_msg(const string& msg)
{
send_message(msg);
}
};
struct Printer
{
void print(const string& msg) { std::cout << msg << std::endl; };
};
int main()
{
{
Printer p;
MessageSource s;
s.connect(&Printer::print, &p);
s.send_msg("test");
}
system("pause");
return 0;
}
I think the magic here is the fact that boost::bind() is able to handle a variety of types for its first argument. I just don't get how it can hold onto it in a private field of some sort without knowing the type...
Is this a case where a functor is really the right solution? It seems like member functions are so much more convenient to use...
Based on the comment by cdhowie above, I was able to come up with the following solution using std::function and std::bind:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
struct MessageSource
{
function<void(const string& msg)> _callback;
template<typename A, typename B>
void connect(A func_ptr, B obj_ptr)
{
_callback = bind(func_ptr, obj_ptr, placeholders::_1);
}
void send_msg(const string& msg)
{
if (_callback)
_callback(msg);
}
void disconnect()
{
_callback = nullptr;
}
};
struct Printer
{
void print(const string& msg) { std::cout << msg << std::endl; };
};
int main()
{
{
Printer p;
MessageSource s;
s.connect(&Printer::print, &p);
s.send_msg("test");
s.disconnect();
s.send_msg("test again");
}
system("pause");
return 0;
}
I'm storing a map in a class that has strings as keys and pointers to member functions as values. I'm having trouble calling the right function throw the function pointer.
Here is the code:
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Preprocessor;
typedef void (Preprocessor::*function)();
class Preprocessor
{
public:
Preprocessor();
~Preprocessor();
void processing(const string before_processing);
private:
void take_new_key();
map<string, function> srch_keys;
string after_processing;
};
Preprocessor::Preprocessor()
{
srch_keys.insert(pair<string, function>(string("#define"), &Preprocessor::take_new_key));
}
Preprocessor::~Preprocessor()
{
}
void Preprocessor::processing(const string before_processing)
{
map<string, function>::iterator result = srch_keys.find("#define");
if(result != srch_keys.end())
result->second;
}
void Preprocessor::take_new_key()
{
cout << "enters here";
}
int main()
{
Preprocessor pre;
pre.processing(string("...word #define other word"));
return 0;
}
In function Preprocessor::processing if the string is found in the map then, I call the proper function. The problem is that, in this code, Preprocessor::take_new_key is never called.
Where is the mistake ?
Thanks
The correct syntax is this:
(this->*(result->second))();
That is ugly. So lets try this:
auto mem = result->second; //C++11 only
(this->*mem)();
Use whichever makes you happy.
result->second does not call the function pointer. Try ((*this).*result->second)();
I have made a map of functions. all these functions are void and receive single string parameter.
code:
void f1(string params){...}
void f2(string params){...}
void f3(string params){...}
map<string , void*> funcMap;
funcMap["f1"] =(void*)&f1;
funcMap["f2"] =(void*)&f2;
funcMap["f3"] =(void*)&f3;
how do i call a function?
I tried the next code, but id doesn't work:
void (*func)(string) = &funcMap[commandType];
func(commandParam);
I get this error message:
Server.cpp:160:46: error: cannot convert ‘void**’ to ‘void (*)(std::string) {aka void (*)(std::basic_string<char>)}’ in initialization
using pfunc = void (*)(string);
map<string, pfunc> funcMap;
funcMap["f1"] = f1; //and so forth
And then call:
pfunc f = funcMap[commandType];
(*f)(commandParam);
In general, why throw away type safety? If it's a map of function pointers, declare it to be one.
Why not just have those as separate classes.
Then have the methods as virtual.
You can then have a map between the string and the base class.
i.e.
class Someoperation
{
virtual void Doit() = 0;
};
map<string, Someopertion> ops;
Then
class MyOp : public Someoperation
{
void Doit() { /* Some code here */}
};
Just add objects
ops["Hello"] = MyOp();
then call it
ops["Hello"].Doit();
&funcMap[commandType]
Just drop the &. Your compile error was useful here. It had a void** on the right which is because you took the address of a function pointer. You don't want two levels of indirection there.
Try C++ style. It has overhead for allocation and inheritance, but it's more flexible and extensible if you'll need some more functionality in the future.
#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>
using namespace std;
class Someoperation {
public:
virtual void Doit() = 0;
};
class MyOp1 : public Someoperation {
public:
void Doit() final { cout << "MyOp1" << endl; }
};
class MyOp2 : public Someoperation {
public:
void Doit() final { cout << "MyOp2" << endl; }
};
int main() {
unordered_map<string, unique_ptr<Someoperation> > ops;
ops["1"] = unique_ptr<Someoperation>(new MyOp1);
ops["2"] = unique_ptr<Someoperation>(new MyOp2);
ops["1"]->Doit(); // Out: MyOp1
ops["2"]->Doit(); // Out: MyOp2
return 0;
}