是否可以约束作为参数给定的lambda捕获类型?
例如,是否可以只采取不通过引用捕获任何东西的lambda表达式?C++ lambda捕获约束条件
template <typename F>
void f(const F& lambda) // F must be a lambda that do not capture by ref
{
:::
}
是否可以约束作为参数给定的lambda捕获类型?
例如,是否可以只采取不通过引用捕获任何东西的lambda表达式?C++ lambda捕获约束条件
template <typename F>
void f(const F& lambda) // F must be a lambda that do not capture by ref
{
:::
}
MSalters注意到“非捕获的lambda可以转换为函数指针。”这是什么意思? lambda对象将匹配指向函数参数类型的指针。
将lambda类型转换为指向函数的指令是非常棘手的。这是我尝试遵循一个合规的实现。这有点骇人听闻。
#include <type_traits>
template< typename fn >
struct ptmf_to_pf;
template< typename r, typename c, typename ... a >
struct ptmf_to_pf< r (c::*) (a ...) const >
{ typedef r (* type)(a ...); };
// Use SFINAE to hide function if lambda is not convertible to function ptr.
// Only check that the conversion is legal, it never actually occurs.
template< typename lambda >
typename std::enable_if< std::is_constructible<
typename ptmf_to_pf< decltype(&lambda::operator()) >::type,
lambda >::value >::type
f(lambda arg) {
arg("hello ");
arg("world\n");
}
#include <iostream>
int main() {
int x = 3;
f([](char const *s){ std::cout << s; }); // OK
f([=](char const *s){ std::cout << s; }); // OK
f([=](char const *s){ std::cout << s << x; }); // error
}
这不会接受函数指针作为直接参数,因为模板参数需要解析为函子。您可以通过为ptmf_to_pf
提供专门接受指向函数类型的指针来实现此目的。
另外,如演示所示,它不会接受通过值来捕获任何内容的lambda表达式,也可以通过引用来接受它。 C++没有办法使限制如此具体。
为什么不把lambda作为函数指针传递,然后没有模板? – perreal 2012-03-15 01:37:08
@perreal:如果你知道所需的函数指针类型,那就这样做。在一般情况下,这是不知道的。 – Potatoswatter 2012-03-15 02:20:19
也许你误解lambda表达式的捕捉行为:一个闭包对象就像是一个仿函数对象阐明,所以
struct Fun
{
Fun (int & a) : n(a) { }
int operator()(...) { ... }
private:
int & n;
};
int q;
Fun f(q);
f(...);
是完全一样的
int q;
auto f = [&q](...) -> int { ... };
f(...);
构建闭包对象后,所有捕获和绑定都会完成并永久锁定到对象中。
如果您现在将对象传递到其他位置,如call_me(f)
,则收件人函数与函子或闭包对象的构造没有关系。
这是真的,但lambda的编译器生成类型包含捕获发生的所有细节。人们可以很容易地想象一个元数据系统,它允许自省这种类型来查看是否有任何引用成员(或者构造函数是否有任何引用参数)。 – 2012-03-12 14:06:31
@BenVoigt是的,这可能是仿函数对象的特征... – log0 2012-03-12 14:07:50
间接破解:只有非捕获的lambda可以转换为指向函数的指针。当然,这也涵盖了很多不属于lambda的F
类型。
允许非lambda函数指针可能是无害的或有益的。+1 – Potatoswatter 2012-03-14 09:20:16
当闭包对象碰到你的函数时,它已经被构造了,你不知道它的内部是什么,因为它们是私有的。但是,如果你想知道,lambda当然不能捕获任何*事后*,尤其是* *你的*函数'f'中没有任何东西。 – 2012-03-12 13:55:32
这样做毫无意义,因为按值捕获指针与捕获参考一样危险。 – 2012-03-12 14:01:34
@BenVoigt没错。 – log0 2012-03-12 14:02:40