我希望有一个地图将字符串键映射到std::function<T()>
或std::function<T(int)>
(但对于给定的键不是两者)。我收到一个编译错误,似乎没有std::function<T(...)>
的模板。我希望能够使用lambdas作为值。
首先,以这种方式存储功能是安全吗?其次,如果是这样,语法是什么? (当从地图中检索到函数时,函数是一元函数还是无效函数。)如果不是上述函数,那么什么是合理的替代方案?指针杀死了lambda的想法,对吧......
C ++ 11没问题。
答案 0 :(得分:5)
一种替代方法是将一个nullary函数包装在一个包装器lambda中,它接受一个参数,对它没有任何作用,只是调用包装函数。然后地图中的所有内容都是一元函数。
当然,如果你在检索时知道这个函数是什么类型的(我想你必须这样做,否则它就没用了!),那么为什么不使用两个地图?
答案 1 :(得分:2)
也许试试boost::variant
?
std::map<std::string, boost::variant<std::function<T()>, std::function<T(int)> > >
无论如何,这似乎是XY question。您想要做什么完全?
答案 2 :(得分:2)
空std::function
并不那么沉重。您可以只映射到包含每个结构的结构。你知道哪个是有效的,所以只能访问那个。
如果您的模板代码需要统一操作而不作为参数传递:
#include <string>
#include <functional>
#include <map>
#include <tuple>
#include <iostream>
#include <math.h>
template<typename T>
using my_maps = std::tuple< std::map<std::string, std::function<T()>>, std::map<std::string, std::function<T(int)>>>;
int main() {
my_maps<double> maps;
std::get<0>(maps)["pi"] = [](){ return 3.14; };
std::get<1>(maps)["e^"] = [](int x){ return pow( 2.7, x ); };
std::cout << std::get<1>(maps)["e^"](2) << "\n";
std::cout << std::get<0>(maps)["pi"]() << "\n";
}
这有两张地图,访问权限与get<0>
或get<1>
不同。这样做的好处是,如果要在模板中选择要访问的两个中的哪一个,它可以静态选择0或1并使用公共代码。如果您不需要,只需要两个std::map
s。
boost::variant
也有效(映射到0ary或1ary函数的variant
)。您还可以在union
中使用C ++ 11 struct
(注意它没有默认构造函数或复制构造函数,除非您提供一个构造函数)并使用枚举(执行副本) union
) - 基本上是一个贫民区boost::variant
。