c++14用于函数绑定的可变lambda捕获
c++14 Variadic lambda capture for function binding
我目前正在读几本书来了解c++14的特性。我正在尝试使用可变参数模板将参数绑定到函数。我知道如何使用std::bind来实现这一点,但我也想用一个c++14 lambda表达式来实现这个函数,只是为了获得常识和理解,以及任何可能的性能优势。我读到lambdas可以内联,而std::bind不能内联,因为它是通过调用函数指针来实现的。
这是myFunctions.h:的代码
#include <functional>
int simpleAdd(int x, int y) {
return x + y;
}
//function signatures
template<class Func, class... Args>
decltype(auto) funcBind(Func&& func, Args&&...args);
template<class Func, class... Args>
decltype(auto) funcLambda(Func&& func, Args&&...args);
/////////////////////////////////////////////////////////////////
//function definitions
template<class Func, class... Args>
inline decltype(auto) funcBind(Func&& func, Args&&... args)
{
return bind(forward<Func>(func), forward<Args>(args)...);
}
template<class Func, class ...Args>
inline decltype(auto) funcLambda(Func && func, Args && ...args)
{ //The error is caused by the lambda below:
return [func, args...]() {
forward<Func>(func)(forward<Args>(args)...);
};
}
这是我正在运行的主要代码:
#include<iostream>
#include<functional>
#include "myFunctions.h"
using namespace std;
int main()
{
cout << "Application start" << endl;
cout << simpleAdd(5,7) << endl;
auto f1 = funcBind(simpleAdd,3, 4);
cout << f1() << endl;
//error is occurring below
auto f2 = funcLambda(simpleAdd, 10, -2);
cout << f2() << endl;
cout << "Application complete" << endl;
错误C2665"std::forward":2个重载都无法转换所有参数类型
错误C2198"int(__cdecl&)(int,int)":用于调用的参数太少
我认为当变参数被转发到lambda时可能会发生错误,但我真的不确定。
我的问题是,我如何正确地制定这段代码,以便使用lambda来捕获函数及其参数,并在以后调用它。
我读到lambdas可以内联,而std::bind不能内联因为它是通过调用函数指针来实现的。
如果将simpleAdd
传递给某个绑定参数的对象,那么是否使用bind
并不重要。你认为lambda用func
捕获了什么?它是一个函数指针。
lambda与函数指针的情况是关于写入bind(simpleAdd, 2, 3)
与[] { return simpleAdd(2, 3); }
。或者像[](auto&&...args) -> decltype(auto) { return simpleAdd(decltype(args)(args)...); }
那样绑定lambda,而不是直接绑定simpleAdd
(将使用函数指针)。
无论如何,实现它都是令人惊讶的棘手。你不能使用按引用捕获,因为事情很容易被挂起,你不能使用简单的按值捕获,因为即使对于右值,它也总是复制参数,而且你不能在init捕获中进行包扩展。
这遵循std::bind
的语义(调用函数对象并将所有绑定参数作为lvalues传递),除了1)它不处理占位符或嵌套绑定,2)函数调用运算符始终是const
:
template<class Func, class ...Args>
inline decltype(auto) funcLambda(Func && func, Args && ...args)
{
return [func = std::forward<Func>(func),
args = std::make_tuple(std::forward<Args>(args)...)] {
return std::experimental::apply(func, args);
};
}
cppreference有一个std::experimental::apply
的实现。
请注意,这确实打开了reference_wrapper
s,就像bind
一样,因为make_tuple
会打开
您的原始代码会崩溃,因为args
是lambda函数调用运算符中的const
(默认情况下为const
),而forward
最终试图丢弃常量。
您使用一个元组:
template<class Func, class ...Args>
inline decltype(auto) funcLambda(Func && func, Args && ...args)
{ //The error is caused by the lambda below:
auto tpl = make_tuple(std::forward<Args>(args)...);
//Use move just in case Args has move-only types.
return [func, tpl = move(tpl)]() {
apply(func, tpl);
};
}
apply
的定义如下:
namespace detail {
template <class F, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_impl( F&& f, Tuple&& t, std::index_sequence<I...> )
{
return f(std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
template <class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t)
{
return detail::apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>>::value);
}
CCD_ 19是库TS版本之一的特征。使用C++17,apply_impl
可以调用invoke
,这将适用于任何可调用的对象。
- 在 lambda 捕获中声明的变量的类型推导
- 在 C++ 中访问 lambda 捕获初始化变量
- Lambda 捕获、初始值设定项和嵌套结构
- 常量方法中的非常量 lambda 捕获
- Visual C++: MSVC vs. GCC+CLANG: 处理 lambda 捕获类成员变量,正确的方法是什么?
- 在嵌套 lambda 的情况下如何初始化 lambda 捕获?
- Lambda 捕获条款的问题
- C++ lambda - 捕获静态成员变量
- 当lambda执行时,C++lambda捕获的引用具有不同的值
- 如何从lambda捕获父目录
- 组合 lambda 捕获时出现编译错误
- 函数参数计算顺序与 Lambda 捕获评估顺序
- C++:读取 Lambda 捕获的指针时出现访问冲突
- Lambda 捕获此函数和长时间运行的函数
- "Empty base optimization" lambda 捕获 - 标准禁止?为什么?
- C++11 lambda 捕获"this"并按值捕获局部变量
- "this" Lambda 捕获的是不正确的。海湾合作委员会编译器错误?
- 将类成员指针传递给 Lambda 捕获列表 c++11
- C++ 宏和 lambda 捕获
- 在折叠表达式中扩展参数包作为 lambda 捕获的一部分 - gcc 与 clang