I try to find a way to call functions depending on one String-Parameter.
Enums or Int are ok too for the Parametertype. Maybe there is something more ?
Is there a way to do it like this:
myFunction(string functionParameter, int value){
this->functionParameter(value);}
What is the best way for this? I know there are some similar Questions, but i didnt found a Answer that really fits my Problem.
Just use a map to map from strings to functions:
void f1()
{
std::cout << "f1!" << std::endl;
}
void f2()
{
std::cout << "f2!" << std::endl;
}
void f3()
{
std::cout << "f3!" << std::endl;
}
int main()
{
std::unordered_map<std::string,std::function<void()>> map;
map["f1"] = f1;
map["f2"] = f2;
map["f3"] = f3;
map["f1"]();
map["f2"]();
map["f3"]();
}
This outputs:
f1!
f2!
f3!
C++ doesn't have direct support to call functions using the name. You'll need to create the mapping somehow. The easiest approach is probably to create a map of a suitable std::function<...> type:
void f(int);
void g(int);
typedef std::function<void(int)> Function;
std:: map<std::string, Function> functions;
// ...
functions["f"] = f;
functions["g"] = g;
void call(std::string const& name, int x) {
auto it = functions.find(name);
if (it->second != functions.end()) {
it->second(x);
}
else {
// deal with unknown functions
}
}
You can map the string to the function pointer. Try something like this:
#include <iostream>
#include <string>
#include <functional>
#include <map>
class X;
template<class X>
class handler_factory;
template<>
class handler_factory<X>
{
private:
using HandlerType = void (X::*)(int);
public:
handler_factory();
HandlerType get(const std::string& name) const
{
if (handlers.find(name) == handlers.end())
return nullptr;
else
return (*handlers.find(name)).second;
}
private:
std::map<std::string, HandlerType> handlers;
};
class X
{
public:
friend class handler_factory<X>;
private:
void f(int);
void h(int);
};
handler_factory<X>::handler_factory()
{
handlers["f"] = &X::f;
handlers["h"] = &X::h;
}
void X::f(int) { std::cout << "X::f();"; }
void X::h(int) { std::cout << "X::h();"; }
Your class (in this example X) can have a function dispatch_method that looks like:
template<typename... Args>
void dispatch_method(const std::string& name, Args&&... args)
{
if (find_handler(name))
(this->*find_handler(name))(std::forward<Args>(args...));
}
Where find_handler is a helper method:
private:
auto find_handler(const std::string& name)
-> decltype(handler_factory<X>().get(name))
{
return handler_factory<X>().get(name);
}
Then you can call it like this:
int main()
{
X{}.dispatch_method("f", 5);
}
You may use something like:
#include <map>
#include <functional>
#include <stdexcept>
#include <string>
template<typename T> class Caller;
template<typename Ret, typename... Args>
class Caller<std::function<Ret(Args...)>>
{
public:
typedef std::function<Ret(Args...)> FuncType;
void add(const std::string& name, FuncType f)
{
functions[name] = f;
}
Ret call(const std::string& name, Args... args)
{
auto it = functions.find(name);
if (it == functions.end()) {
// Or any other error
throw std::runtime_error("unknown " + name + "function");
}
return (it->second)(args...);
}
private:
std::map<std::string, FuncType> functions;
};
So lets test it:
int minus(int a) { return -a; }
int main(int argc, char** argv)
{
Caller<std::function<int (int)>> caller;
caller.add("+1", [](int a) { return a + 1; } );
caller.add("minus", minus);
caller.call("minus", -42); // calls minus(-42), returns 42
caller.call("+1", 41); // calls the lambda, returns 42
return 0;
}
This is similar to question here. You need to create a map like this map<string, class::method>, then you can use its signature to search for function and call it.
Two ways are available for you:
1. Without using any 3rd-party library (in row C++):
#include <map>
#include <string>
struct Math
{
double sinFunc(double x) { return 0.33; };
double cosFunc(double x) { return 0.66; };
};
typedef double (Math::*math_method_t)(double);
typedef std::map<std::string, math_method_t> math_func_map_t;
int main()
{
math_func_map_t mapping;
mapping["sin"] = &Math::sinFunc;
mapping["cos"] = &Math::cosFunc;
std::string function = std::string("sin");
math_func_map_t::iterator x = mapping.find(function);
int result = 0;
if (x != mapping.end()) {
Math m;
result = (m.*(x->second))(20);
}
}
2. By using Boost library: The most convenient notation for method is function<signature> where function is either included in boost or in <utility>.
The signature would be like this.
map<string, function<double (double)> map; ...
map["sin"](1.0);
Related
I have two functions which need to be exposed by the class and they look like this (more will follow):
void print_a(std::string s);
void print_b(std::string s, int val);
"Under the hood" they are doing the same exact thing namely doing a lookup in a map and passing the call parameters to the function pointer retrieved by the map:
#include <stdint.h>
#include <iostream>
#include <string>
#include <map>
class Thing{
private:
void do_a(){
std::cout << "hello";
}
//there might be also a method do_a_extended() which has a different key in the map
void do_b(int age){
std::cout << "my age is " << age;
}
typedef void (Thing::*do_stuff_a)();
typedef void (Thing::*do_stuff_b)(int);
std::map<std::string, do_stuff_a> a_table;
std::map<std::string, do_stuff_b> b_table;
public:
void print_a(std::string s){
do_stuff_a handler = a_table[s];
if(handler){
(this->*handler)();
}
}
void print_b(std::string s, int val){
do_stuff_b handler = b_table[s];
if(handler){
(this->*handler)(val);
}
}
};
I dislike the fact that there is a lot of boilerplate code involved. I wonder if its possible to pass a member into template so I can do this:
class Thing{
private:
void do_a(){
std::cout << "hello";
}
void do_b(int age){
std::cout << "my age is " << age;
}
typedef void (Thing::*do_stuff_a)();
typedef void (Thing::*do_stuff_b)(int);
std::map<std::string, do_stuff_a> a_table;
std::map<std::string, do_stuff_b> b_table;
template<<MAP_MEMBER>,typename ... PP>
void print_x(std::string s, PP &&... pp){
auto handler = <MAP_MEMBER>[s];
if(handler){
(this->*handler)(std::forward<PP>(pp) ...);
}
}
public:
typedef decltype(print_x<a_table>) print_a;
typedef decltype(print_x<b_table>) print_b;
};
Any ideas on how to get rid of boilerplate is appreciated.
No need to get complicated, just use your printers as wrappers that pass a member to a generic print method like so:
class Foo
{
int a;
char b;
template <typename M>
void Print (M & member)
{
// complicated function
}
public:
void PrintA ()
{
Print(a);
}
void PrintB ()
{
Print(b);
}
};
So in your example the public print functions become wrapper functions:
class Thing
{
// ...
template <typename T, typename ... PP>
void print (T & table, const std::string & key, PP && ... pp)
{
auto method = table[key];
if (method)
(this->*method)(std::forward<PP>(pp)...);
}
public:
template <typename ... PP>
void print_a (PP && ... pp)
{
print(a_table, std::forward<PP>(pp)...);
}
template <typename ... PP>
void print_b (PP && ... pp)
{
print(b_table, std::forward<PP>(pp)...);
}
};
These public methods should be inlined if you use -O3 optimisation.
Here's a running solution with less boilerplate and no need for metaprogramming:
#include <iostream>
#include <string>
#include <map>
class Thing
{
void do_a_1 ()
{
std::cout << "hello" << std::endl;
}
void do_a_2 ()
{
std::cout << "goodbye" << std::endl;
}
void do_b (int age)
{
std::cout << "my age is " << age << std::endl;
}
template <typename ... PP>
using MapMethod = std::map<std::string, void (Thing::*)(PP...)>;
MapMethod<> a_table;
MapMethod<int> b_table;
template <typename T>
void insert (T) {}
template <typename T, typename M, typename ... PP>
void insert (T & table, const std::string & key, M && method, PP && ... pp)
{
table.insert({key, method});
insert(table, pp...);
}
template <typename T, typename ... PP>
void print (const T & table, const std::string & key, PP && ... pp)
{
auto result = table.find(key);
if (result != table.end())
{
auto method = result->second;
(this->*method)(pp...);
}
}
public:
Thing ()
{
insert(a_table,
"apple", &Thing::do_a_1,
"banana", &Thing::do_a_2);
insert(b_table,
"ostrich", &Thing::do_b);
}
void print_a (const std::string & key)
{
print(a_table, key);
}
void print_b (const std::string & key, int val)
{
print(b_table, key, val);
}
};
int main ()
{
Thing t;
t.print_a("apple");
t.print_b("ostrich", 12);
t.print_a("banana");
t.print_a("Do nothing");
}
If somehow your wrapper methods are unavoidably repetitive in your real problem (perhaps perfect forwarding is getting tiresome), you could reduce boilerplate further with a macro to make the print methods:
class Thing
{
// private code is the same, except:
// there's no need for the generic print method anymore
public:
Thing ();
#define PRINT_MACRO(FUNCTION_NAME, MEMBER_TABLE) \
template <typename ... PP> \
void FUNCTION_NAME (const std::string & key, PP && ... pp) \
{ \
auto result = MEMBER_TABLE.find(key); \
if (result != MEMBER_TABLE.end()) \
{ \
auto method = result->second; \
(this->*method)(pp...); \
} \
}
PRINT_MACRO(print_a, a_table)
PRINT_MACRO(print_b, b_table)
#undef PRINT_MACRO
};
Lastly, are you sure that you wanted to use std::map instead of std::unordered_map? This problem suggests that you don't care about the ordering.
Macros or code generation are the way to go when you want to define things that require concatenating in identifiers.
In particular, since you also need to handle an arbitrary number of parameters in the generated code, I'd go with code generation.
You could extract the map to an extra class that can also handle searching and calling entries:
template <typename C, typename K, typename...Args>
class MemberFunctionCaller
{
private:
using FunctionType = void(C::*)(Args...);
using MapType = std::map<K, FunctionType>;
MapType registry;
public:
void Register(const K& key, FunctionType value)
{
registry[key] = value;
}
void Call(const K& key, C* self, const Args&...args)
{
auto iter = registry.find(key);
if(iter != registry.end())
{
FunctionType func = iter->second;
(self->*func)(args...);
}
}
};
A simple typedef would simplify the usage inside your "Thing"-class:
template <typename...Args>
using ThingFunctionCaller = MemberFunctionCaller<Thing, std::string, Args...>;
The thing class could look somewhat like this:
class Thing{
template <typename...Args>
using ThingFunctionCaller = MemberFunctionCaller<Thing, std::string, Args...>;
private:
void do_a(){
std::cout << "hello" << std::endl;
}
void do_b(int age){
std::cout << "my age is " << age << std::endl;
}
ThingFunctionCaller<> a_table;
ThingFunctionCaller<int> b_table;
public:
void print_a(std::string s){
a_table.Call(s, this);
}
void print_b(std::string s, int val){
b_table.Call(s, this, val);
}
};
And that's what it would look like in Action: https://gcc.godbolt.org/z/KM5a85
You could use a static template registry that stores the relation between name and member function.
This has other disadvantages but would work in your particular use case.
(With some additional coding you could even make this work more "natural").
template <typename C, typename...Args>
using MemberFunctionPointer = void(C::*)(Args...);
template <typename C, typename...Args>
class MemberFunctionCaller
{
private:
using FunctionType = MemberFunctionPointer<C, Args...>;
using MapType = std::map<std::string, FunctionType>;
static MapType& GetRegistry(){
static MapType registry;
return registry;
}
public:
static void Register(const std::string& key, FunctionType function)
{
auto& registry = GetRegistry();
registry[key] = function;
}
static void Call(const std::string& key, C* self, const Args&...args)
{
auto& registry = GetRegistry();
auto iter = registry.find(key);
if(iter != registry.end())
{
FunctionType func = iter->second;
(self->*func)(args...);
}
}
};
template <typename C>
class MemberFunctionRegistry
{
public:
template <typename...Args>
static void Register(const std::string& key, MemberFunctionPointer<C, Args...> function)
{
MemberFunctionCaller<C, Args...>::Register(key, function);
}
template <typename...Args>
static void Call(const std::string& key, C* self, const Args&...args)
{
MemberFunctionCaller<C, Args...>::Call(key, self, args...);
}
};
Your Thing class could look like this:
class Thing{
private:
void do_a(){
std::cout << "hello" << std::endl;
}
void do_a_extended(){
std::cout << "hello world" << std::endl;
}
void do_b(int age){
std::cout << "my age is " << age << std::endl;
}
MemberFunctionRegistry<Thing> registry;
public:
static void RegisterMemberFunctions()
{
MemberFunctionRegistry<Thing>::Register("A", &Thing::do_a);
MemberFunctionRegistry<Thing>::Register("AX", &Thing::do_a_extended);
MemberFunctionRegistry<Thing>::Register("B", &Thing::do_b);
}
template <typename...Args>
void print_x(std::string s, Args...args){
registry.Call(s, this, args...);
}
};
https://gcc.godbolt.org/z/fq5bez
How can I create a variable of generalised std::function type that can take any callable objects? I can't use variadic templates because it'll create a family of different types, while I need a single type, so that I can take different [&] lambdas to a same array.
I did it with functors (example below) that produce std::function<void()>, but for this I have to create a functor for every set of arguments that my functions use. Now I want to use lambdas to bind arguments, but their type is tricky and I can't get different lambdas to the same array.
I understand that this will be very unsafe.
#include <iostream>
#include <vector>
#include <string>
using ChoiceArray = std::vector<std::function<void()>>;
int GetInt(int restriction);
class MenuFunctor {
private:
std::string output;
ChoiceArray arrayOfFunctions;
public:
MenuFunctor(std::string n_output, ChoiceArray n_arrayOfFunctions)
: output(n_output), arrayOfFunctions(n_arrayOfFunctions)
{ }
void operator()() const {
int selection;
std::cout << output;
selection = GetInt(int(arrayOfFunctions.size()));
arrayOfFunctions[selection]();
}
};
class OperationFunctor {
private:
std::function<void(std::vector<std::string>*)> func;
std::vector<std::string>* container;
public:
OperationFunctor(std::function<void(std::vector<std::string>*)> n_func, std::vector<std::string>* n_container)
: func(n_func), container(n_container)
{ }
void operator()() const {
func(container);
}
};
void Func1(std::vector<std::string>* container);
void Func2(std::vector<std::string>* container);
void Func3(std::vector<std::string>* container);
int main() {
std::vector<std::string> container;
std::vector<std::string>* containerAddress = &container;
OperationFunctor f1(Func1, containerAddress);
OperationFunctor f2(Func2, containerAddress);
OperationFunctor f3(Func3, containerAddress);
ChoiceArray Array = {f1, f2, f3};
MenuFunctor Start("input 0-2\n", Array);
Start(); // Works
return 0;
}
Also, I tried to take std::vector<std::string> container for Func1-Func3 by reference, but it didn't work, so I went with pointers. It has something to do with perfect forwarding?
Just stuff lambdas into std::function<void()>.
using OperationFunctor = std::function<void()>;
using ChoiceArray = std::vector<OperationFunctor>;
int GetInt(int restriction);
class MenuFunctor {
private:
std::string output;
ChoiceArray arrayOfFunctions;
public:
MenuFunctor(std::string n_output, ChoiceArray n_arrayOfFunctions)
: output(n_output), arrayOfFunctions(n_arrayOfFunctions)
{ }
void operator()() const {
int selection;
std::cout << output;
selection = GetInt(int(arrayOfFunctions.size()));
arrayOfFunctions[selection]();
}
};
void Func1(std::vector<std::string>* container);
void Func2(std::vector<std::string>* container);
void Func3(std::vector<std::string>* container);
int main() {
std::vector<std::string> container;
std::vector<std::string>* containerAddress = &container;
OperationFunctor f1([containerAddress]{ Func1(containerAddress) });
OperationFunctor f2([containerAddress]{ Func2(containerAddress) });
OperationFunctor f3([containerAddress]{ Func3(containerAddress) });
ChoiceArray Array = {f1, f2, f3};
MenuFunctor Start("input 0-2\n", Array);
Start(); // Works
return 0;
}
assuimng this example code
#include <vector>
#include <iostream>
#include <algorithm>
#include <unistd.h>
template< typename T, typename S >
class MyClass
{
public:
MyClass () : v(10) {}
bool ok () { return true; }
T run (S s, int i) { return v.at(i) = s(); }
private:
std::vector<T> v;
};
int main ()
{
auto f_int = [=]() -> int { sleep(1); return 15; };
MyClass<int, stdmc::function< int(void) > > mc_int;
std::cout << mc_int.run(f_int, 1) << std::endl;
return 0;
}
I want to make partial template specialization for T=void type without rewriting duplicite code. Obviously I only need to reimplement run and possibly get rid of vector as it can't store void type.
There is a lot of literature covering this topic (using enums or int template params), however not a single example of similar problems (i.e. reimplementing only one method and problematic vector).
My motivation is obvious - I need common methods written only once for future code revisions.
My attempt (using code above):
template< typename S >
class MyClass<void, S>
{
public:
// same constructor
// same ok() method
void run (S s, int i) { return s(); }
private:
// without std::vector<T> v;
};
// ----- main ------
auto f_void = [=]() -> void { sleep(1); };
MyClass<void, std::function< void(void) > > mc_void;
std::cout << mc_void.run(f_void, 1) << std::endl;
Is there any way implementing this behaviour in c++11? If so, what is the proper syntax? If not, what do you recommend - copying the whole class while correcting only one method or restructing whole class completely in order to avoid these problems (maybe use vector<T*> which should be able to store void*)?
thanks to Oktalist - this seems to work
#include <vector>
#include <iostream>
#include <algorithm>
#include <unistd.h>
class Base
{
public:
bool ok () { return true; }
};
template< typename T, typename S >
class MyClass : public Base
{
public:
MyClass () : v(10) {}
T run (S s, int i) { return v.at(i) = s(); }
private:
std::vector<T> v;
};
template< typename S >
class MyClass<void, S> : Base
{
public:
MyClass () = default;
void run (S s, int i) { return s(); }
};
int main ()
{
auto f_int = [=]() -> int { sleep(1); return 15; };
MyClass<int, std::function< int(void) > > mc_int;
std::cout << mc_int.run(f_int, 1) << std::endl;
auto f_void = [=]() -> void { sleep(1); std::cout << "done" << std::endl; };
MyClass<void, std::function< void(void) > > mc_void;
mc_void.run(f_void, 1);
return 0;
}
This is related to this previous question: Using boost::bind with boost::function: retrieve binded variable type.
I can bind a function like this:
in .h:
class MyClass
{
void foo(int a);
void bar();
void execute(char* param);
int _myint;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
myVector.push_back(boost::bind(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
f();
}
But how can I bind a return value ? i.e.:
in .h:
class MyClass
{
double foo(int a);
void bar();
void execute(char* param);
int _myint;
double _mydouble;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
//PROBLEM IS HERE: HOW DO I BIND "_mydouble"
myVector.push_back(boost::bind<double>(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
double returnval;
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
//THIS DOES NOT WORK: cannot convert 'void' to 'double'
// returnval = f();
//MAYBE THIS WOULD IF I COULD BIND...:
// returnval = _mydouble;
}
If what you want is a nullary function that returns void but assigns a value to _myDouble with the result of foo() before doing so, then you cannot do this easily with just Boost.Bind. However, Boost has another library specifically catered to this sort of thing -- Boost.Phoenix:
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/phoenix/phoenix.hpp>
struct MyClass
{
MyClass() : _myVector(), _myInt(), _myDouble() { }
void setMyInt(int i);
void bar();
void execute();
private:
double foo(int const a) { return a * 2.; }
std::vector<boost::function<void()> > _myVector;
int _myInt;
double _myDouble;
};
void MyClass::setMyInt(int const i)
{
_myInt = i;
}
void MyClass::bar()
{
using boost::phoenix::bind;
_myVector.push_back(
bind(&MyClass::_myDouble, this) =
bind(&MyClass::foo, this, bind(&MyClass::_myInt, this))
);
}
void MyClass::execute()
{
if (_myVector.empty())
return;
_myVector.back()();
double const returnval = _myDouble;
std::cout << returnval << '\n';
}
int main()
{
MyClass mc;
mc.bar();
mc.setMyInt(21);
mc.execute(); // prints 42
mc.setMyInt(3);
mc.execute(); // prints 6 (using the same bound function!)
// i.e., bar has still only been called once and
// _myVector still contains only a single element;
// only mc._myInt was modified
}
problem 1: myVector needs to be a class member.
problem 2: myVector is interested in functions that return doubles and take no arguments, which would be boost::function<double()>
then, to bind _mydouble to the parameter of foo, call boost::bind(&MyClass::foo, this, MyClass::_mydouble) which should give you a compilation warning about casting a double to an int for when foo is called.
The closest you can come with Boost.Bind is providing the toreturn as a parameter.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std;
class Foo {
int myInt;
double myDouble;
public:
Foo() : myInt(3), myDouble(3.141592) { }
void SetToMyInt(double& param)
{
param = myInt;
}
void SetToMyDouble(double& param)
{
param = myDouble;
}
double Execute()
{
double toReturn = 2;
boost::function<void(double&)> f = boost::bind(&Foo::SetToMyDouble, this, _1);
f(toReturn);
return toReturn;
}
};
int main() {
Foo foo;
std::cout << foo.Execute() << std::endl;
return 0;
}
I'm trying to store a set of std::function in a map (under GCC 4.5)
I'd like to get 2 kind of things :
storing functions with arguments already passed; then you just have
to call f()
storing functions without arguments; then you have to call
f(...)
I think I achieved the first one with a class Command and a Manager :
class Command
{
std::function<void()> f_;
public:
Command() {}
Command(std::function<void()> f) : f_(f) {}
void execute() { if(f_) f_(); }
};
class CommandManager
{
typedef map<string, Command*> FMap;
public :
void add(string name, Command* cmd)
{
fmap1.insert(pair<string, Command*>(name, cmd));
}
void execute(string name)
{
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
Command* c = it->second;
c->execute();
}
}
private :
FMap fmap1;
};
can be used like this :
class Print{
public:
void print1(string s, string s1){ cout<<"print1 : "<<"s : "<<s<<" s1 : "<<s1<<endl; }
int print2(){ cout<<"print2"<<endl; return 2;}
};
#include <string>
#include <functional>
int main()
{
Print p = Print();
function<void()> f1(bind(&Print::print1, &p, string("test1"), string("test2")));
function<int()> f2(bind(&Print::print2, &p));
CommandManager cmdMgr = CommandManager();
cmdMgr.add("print1", new Command(f1));
cmdMgr.execute("print1");
cmdMgr.add("print2", new Command(f2));
cmdMgr.execute("print2");
return 0;
}
Now I'd like to be able to do this :
int main()
{
Print p = Print();
function<void(string, string)> f1(bind(&Print::print1, &p, placeholders::_1, placeholders::_2));
CommandManager cmdMgr = CommandManager();
cmdMgr.add("print1", new Command(f1));
cmdMgr.execute("print1", string("test1"), string("test2"));
return 0;
}
Is there a way, using type-erasure for example ?
You could use dynamic cast to determine the type of the function in the list at runtime.
Please note that I added shared_ptr to remove the memory leak in the original sample. Perhaps you want to throw a exception if the execute method is called with the wrong arguments (if the dynamic_cast yields 0).
Usage:
void x() {}
void y(int ) {}
void main() {
CommandManager m;
m.add("print", Command<>(x));
m.add("print1", Command<int>(y));
m.execute("print");
m.execute("print1", 1);
}
Code (with variadic template support for example gcc-4.5):
#include <functional>
#include <map>
#include <string>
#include <memory>
using namespace std;
class BaseCommand
{
public:
virtual ~BaseCommand() {}
};
template <class... ArgTypes>
class Command : public BaseCommand
{
typedef std::function<void(ArgTypes...)> FuncType;
FuncType f_;
public:
Command() {}
Command(FuncType f) : f_(f) {}
void operator()(ArgTypes... args) { if(f_) f_(args...); }
};
class CommandManager
{
typedef shared_ptr<BaseCommand> BaseCommandPtr;
typedef map<string, BaseCommandPtr> FMap;
public :
template <class T>
void add(string name, const T& cmd)
{
fmap1.insert(pair<string, BaseCommandPtr>(name, BaseCommandPtr(new T(cmd))));
}
template <class... ArgTypes>
void execute(string name, ArgTypes... args)
{
typedef Command<ArgTypes...> CommandType;
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
CommandType* c = dynamic_cast<CommandType*>(it->second.get());
if(c)
{
(*c)(args...);
}
}
}
private :
FMap fmap1;
};
without variadic template support (example VS2010):
#include <functional>
#include <map>
#include <string>
#include <memory>
using namespace std;
class Ignored;
class BaseCommand
{
public:
virtual ~BaseCommand() = 0 {};
};
template <class A1 = Ignored>
class Command : public BaseCommand
{
typedef std::function<void(A1)> FuncType;
FuncType f_;
public:
Command() {}
Command(FuncType f) : f_(f) {}
void operator()(const A1& a1) { if(f_) f_(a1); }
};
template <>
class Command<Ignored> : public BaseCommand
{
typedef std::function<void()> FuncType;
FuncType f_;
public:
Command() {}
Command(FuncType f) : f_(f) {}
void operator()() { if(f_) f_(); }
};
class CommandManager
{
typedef shared_ptr<BaseCommand> BaseCommandPtr;
typedef map<string, BaseCommandPtr> FMap;
public :
template <class T>
void add(string name, const T& cmd)
{
fmap1.insert(pair<string, BaseCommandPtr>(name, BaseCommandPtr(new T(cmd))));
}
template <class A1>
void execute(string name, const A1& a1)
{
typedef Command<A1> CommandType;
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
CommandType* c = dynamic_cast<CommandType*>(it->second.get());
if(c)
{
(*c)(a1);
}
}
}
void execute(string name)
{
typedef Command<> CommandType;
FMap::const_iterator it = fmap1.find(name);
if(it != fmap1.end())
{
CommandType* c = dynamic_cast<CommandType*>(it->second.get());
if(c)
{
(*c)();
}
}
}
private :
FMap fmap1;
};
What you are trying to do is not possible without some serious runtime work and the associated cost. The simplest solution would of course to just store a boost::any (any_function never made it into boost) inside your map and do the necessary casts (or add some runtime data that tells you which cast to make), although you should avoid that at any cost and go with fixed arguments or no arguments.
Your users can then modify their functions using bind to match the signature you require.
Edit: In your current scheme I see no reason for CommandManager to store Command* in the map.
Edit2: Also you drop the return type. This could be OK for your use-case but makes this a lot less generic.
Edit3: I worked out some working example of your code using any. I feel that there is some flaw and I really don't see what this should achieve but here it goes:
#include <iostream>
#include <string>
#include <map>
#include <functional>
#include <boost/any.hpp>
class AnyCaller
{
std::map<std::string, boost::any> calls;
public:
AnyCaller() {}
void add(const std::string& name, const boost::any& fun) {
calls[name] = fun;
}
// we always use the throwing version of any_cast
// icbb by error checking
// no arg version
template<typename Ret>
Ret call(const std::string& s) {
const boost::any& a = calls[s];
return boost::any_cast< std::function<Ret(void)> >(a)();
}
// this should be a variadic template to be actually usable
template<typename Ret, typename T>
Ret call(const std::string& s, T&& arg) {
// we have to assume that our users know what we are actually returning here
const boost::any& a = calls[s];
return boost::any_cast< std::function<Ret(T)> >(a)(std::forward<T>(arg));
}
virtual ~AnyCaller() {}
};
int foo() { std::cout << "foo" << std::endl; return 1; }
double foo2(int i) { std::cout << "foo2" << std::endl; return double(i); }
int main()
{
AnyCaller c;
c.add("foo", std::function<int(void)>(foo));
c.add("foo2", std::function<double(int)>(foo2));
c.call<int>("foo");
c.call<double, int>("foo2", 1);
// this should throw
c.call<double, int>("foo", 1);
return 0;
}
As for the example using a fixed signature. Just think of what would be the most natural representation of a function you are going to store (looking at your Command example I'd assume it is std::function<void(void)>. Store functions of this type and whenever one your users tries to use it, he has to bind whatever function he wants to use, so it matches this signature.
Your Command class constructor needs a function<void()>. You are trying to feed it a function<void(string,string)>. This is not going to typecheck.
If you need functions that accept variable arguments (like printf), you will need function<> and execute() that accept variable arguments. You need to know how to work with that (in particular, you need a fixed first argument). You are then responsible for type safety, much like with printf.
If you just need a variable number of string arguments, use functions that accept e.g. vectors of strings.
All this has nothing to do whatsoever with std::map. Whatever you can store in a plain old variable, you can store in std::map too.