我想知道是否有一种方法可以将仅具有现代C ++的具有不同签名的功能对象(函数,回调,...)存储在标准容器(std :: map)中。管理容器的库不知道其“客户端”将使用哪些签名。
我的需求与此处公开的需求相同:如何在容器中存储具有不同签名的功能对象?,而这个解决方案https://stackoverflow.com/a/8304873/4042960对我来说是完美的:我只想做同样的事情而无需加倍努力。据我所知,没有std :: any。对我来说,最好的解决方案是存储std :: function而不对其进行专门化处理,但是如果可能的话,我不知道该怎么做。
编辑:
用您给我的答案,我写了这个例子:
#include <map>
#include <memory>
#include <functional>
#include <string>
#include <iostream>
#include <stdexcept>
class FunctionMap
{
struct Base {
virtual ~Base() {}
};
template<class R, class... Args>
struct Func : Base
{
std::function<R(Args...)> f;
};
std::map<std::string, std::shared_ptr<Base> > _map;
public:
template<class R, class... Args>
void store(const std::string &key, const std::function<R(Args...)> &f) {
auto pfunc = std::make_shared<Func<R, Args...> >();
pfunc->f = f;
_map.insert(std::make_pair(key, pfunc));
}
template<class R, class... Args>
std::function<R(Args...)> get(const std::string &key) {
auto pfunc = std::dynamic_pointer_cast<Func<R, Args...> >(_map[key]);
if (pfunc)
return pfunc->f;
else
throw std::runtime_error("Bad type for function's parameters");
}
};
// test
int plus(int a, int b) { return a+b; }
double multiplies(double x, double y) { return x*y; }
int main()
{
FunctionMap fm;
fm.store("plus", std::function<int(int, int)>(&plus));
fm.store("multiplies", std::function<double(double, double)>(&multiplies));
// fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1));
std::cout << "5 + 3 = " << fm.get<int, int, int>("plus")(5, 3) << std::endl;
std::cout << "5 * 3 = " << fm.get<double, double, double>("multiplies")(5.0, 3.0) << std::endl;
return 0;
}
这很好用,但是我想对其进行一些改进:
1)我希望能够使用std::bind
:fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1));
但目前无法编译;
2)我想用fm.get<int (int, int)>("plus")
代替,fm.get<int, int, int>("plus")
但我不知道该怎么做。
非常感谢您的帮助 !
您可以自己编写any
。没有所有的编译器变通办法和东西,boost::any
可以用大约30行代码编写。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句