gpt4 book ai didi

C++0x:在 std::map 中存储任何类型的 std::function

转载 作者:可可西里 更新时间:2023-11-01 17:35:46 25 4
gpt4 key购买 nike

我试图在映射中存储一组 std::function(在 GCC 4.5 下)

我想要两种东西:

  • 存储参数已经传递的函数;那么你就有调用 f()
  • 存储不带参数的函数;那么你必须打电话f(...)

我想我用类命令和管理器实现了第一个:

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;

};

可以这样使用:

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;
}

现在我希望能够做到这一点:

 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;
}

有没有办法,例如使用类型删除?

最佳答案

您可以在运行时使用动态转换来确定列表中函数的类型。请注意,我添加了 shared_ptr 以消除原始示例中的内存泄漏。如果使用错误的参数调用 execute 方法(如果 dynamic_cast 产生 0),您可能想抛出异常。

用法:

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);
}

代码(具有可变参数模板支持,例如 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;
};

没有可变参数模板支持(例如 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;
};

关于C++0x:在 std::map 中存储任何类型的 std::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7624017/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com