【发布时间】:2015-06-08 15:07:29
【问题描述】:
我想创建一个以 lambda 作为参数的函数,并返回一个类型取决于 lambda 函数返回类型的对象。 我想要实现的基本上是在实例化时没有显式的模板参数。
现在,这是我的解决方案,我的问题是:有没有更短(更优雅)的方法?
template<typename Func, typename RT = std::unordered_map<int,
decltype(((Func*)nullptr)->operator()(T())) > >
RT mapResult(Func func)
{
RT r;
for (auto &i : mData)
r.insert({i.first, func(mData.second)});
return r;
}
为了更清楚一点,lambda 类型Func 以T& 为参数并返回一个特定类型的向量,mapResult 将func 的结果映射到一个unordered_map 的@ 987654327@ 模板参数是 lambda 函数返回类型(可能是别的东西,但仍然依赖于这种类型)。实际的代码要复杂得多,但我正在努力明确这一点。
我发现避免多次编写RT 类型的唯一解决方案是将它放在模板参数列表中并给它一个默认值,这取决于第一个模板参数(它本身是从函数参数推导出来的) .这有点像定义模板类型名。
我正在使用 VC12,但也想拥有在 g++ 下编译的可移植代码。
然后实例化看起来像这样(虚拟示例):
auto r = c.mapResult([](T &t){return std::vector<int> {(int)t.size()};});
【问题讨论】:
-
" 如果我从 decltype 中删除一组括号,它就不起作用" 你在说哪组括号?
-
@dyp 可能是我的阅读错误。从此代码中,您无法删除括号。我不确定我的原始代码是否有一组额外的括号。编辑:删除问题。
-
演员
((Func*)nullptr)需要一组()因为您使用的是(C 风格)演员表。语法简单地将(T)e->x解释为(T)(e->x)。您可以改用函数样式转换T(e)->x,但这不适用于Func*,因为它不是简单类型说明符。其他演员,如static_cast<T>(e)->x会起作用。最后的括号是operator()的函数调用括号,加上T类型的“强制转换”(创建临时)的括号。它可以写成operator()( T{} ),或者只是(*static_cast<Func*>(nullptr))( T{} )。
标签: c++ templates c++11 lambda decltype