Mor*_*enn 5 c++ lambda templates c++11 std-function
我创建了一个模板类,其中包含std::function一个成员,方法如下:
template<typename Ret, typename... Args>
class Foo
{
private:
std::function<Ret(Args...)> _func;
public:
Foo(const std::function<Ret(Args...)>& func):
_func(func)
{}
};
Run Code Online (Sandbox Code Playgroud)
为了不必指定传递函数的参数和返回类型,我创建了一些make_foo重载:
template<typename Ret, typename... Args>
auto make_foo(Ret (&func)(Args...))
-> Foo<Ret, Args...>
{
return { std::function<Ret(Args...)>(func) };
}
template<typename Ret, typename... Args>
auto make_foo(const std::function<Ret(Args...)>& func)
-> Foo<Ret, Args...>
{
return { func };
}
Run Code Online (Sandbox Code Playgroud)
但是,我无法创建一个make_foo以lambda作为参数的重载:
template<typename Ret, typename... Args>
auto make_foo(??? func)
-> Foo<Ret, Args...>
{
return { std::function<Ret(Args...)>(func) };
}
Run Code Online (Sandbox Code Playgroud)
我只是找不到从lambda自动推导出返回类型和参数类型的方法.有没有一种解决这种问题的惯用方法?
好吧,所以我以为我会死,但我终于做到了 \xc3\xa7_\xc3\xa7
\n\n首先,我使用了常用的索引。由于我没有官方的索引,因此我使用了几个月前编写的旧索引:
\n\ntemplate<std::size_t...>\nstruct indices {};\n\ntemplate<std::size_t N, std::size_t... Ind>\nstruct make_indices:\n make_indices<N-1, N-1, Ind...>\n{};\n\ntemplate<std::size_t... Ind>\nstruct make_indices<0, Ind...>:\n indices<Ind...>\n{};\nRun Code Online (Sandbox Code Playgroud)\n\n然后,我使用了在 StackOverflow 上找到的一些函数特征。它们很好,我认为它们相当于评论中链接的 Boost 库:
\n\ntemplate<typename T>\nstruct function_traits:\n function_traits<decltype(&T::operator())>\n{};\n\ntemplate<typename C, typename Ret, typename... Args>\nstruct function_traits<Ret(C::*)(Args...) const>\n{\n enum { arity = sizeof...(Args) };\n\n using result_type = Ret;\n\n template<std::size_t N>\n using arg = typename std::tuple_element<N, std::tuple<Args...>>::type;\n};\nRun Code Online (Sandbox Code Playgroud)\n\n然后,我能够编写一个适当的make_foo函数及其实现函数,因为两者都需要使用索引。小心点,它很丑陋:
template<typename Function, std::size_t... Ind>\nauto make_foo_(Function&& func, indices<Ind...>)\n -> Foo<\n typename function_traits<typename std::remove_reference<Function>::type>::result_type,\n typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...>\n{\n using Ret = typename function_traits<typename std::remove_reference<Function>::type>::result_type;\n return { std::function<Ret(typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...)>(func) };\n}\n\ntemplate<typename Function, typename Indices=make_indices<function_traits<typename std::remove_reference<Function>::type>::arity>>\nauto make_foo(Function&& func)\n -> decltype(make_foo_(std::forward<Function>(func), Indices()))\n{\n return make_foo_(std::forward<Function>(func), Indices());\n}\nRun Code Online (Sandbox Code Playgroud)\n\n该代码有些丑陋且不可读,但它确实有效。希望它现在不依赖于某些实现定义的行为。另外,谢谢大家的建议,很有帮助!:)
\n\nint main()\n{\n auto lambda = [](int i, float b, long c)\n {\n return long(i*10+b+c);\n };\n\n auto foo = make_foo(lambda);\n std::cout << foo(5, 5.0, 2) << std::endl; // 57, it works!\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这是一个活生生的例子:)
\n| 归档时间: |
|
| 查看次数: |
1390 次 |
| 最近记录: |