考虑下面的代码:
main()
{
bool t;
...
std::function<bool (bool)> f = t ? [](bool b) { return b; } : [](bool b) { return !b; }; // OK
std::function<bool (bool)> f = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error
}
当铿锵3.1编译的,非捕获拉姆达的分配工作,而一个与捕获失败:
main.cpp:12:36: error: incompatible operand types ('<lambda at main.cpp:12:38>' and '<lambda at main.cpp:12:71>')
std::function<bool (bool)> f2 = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
为什么拍摄相同的变量将导致2个lambda表达式是不兼容的类型吗?
该类型拉姆达的是“一个独特的,非工会类类型”之称的闭合类型。 每个拉姆达被实现为不同类型的,本地的声明的范围,它有一个重载操作符()来调用函数体。
例如 :如果你这样写:
auto a=[t](bool b){return t==b;};
auto b=[t](bool b){return t!=b;};
然后编译器编译此(或多或少):
class unique_lambda_name_1
{
bool t;
public:
unique_lambda_name_1(bool t_) t(_t) {}
bool operator () (bool b) const { return t==b; }
} a(t);
class unique_lambda_name_2
{
bool t;
public:
unique_lambda_name_2(bool t_) t(_t) {}
bool operator () (bool b) const { return t!=b; }
} b(t);
A和B有不同的类型,不能在使用?:运算符。
然而,§5.1.2(6)表示,与无捕获的λ的闭合类型具有非显式的,公共的转换运算符,其中的λ转换为一个函数指针 - 非封闭件可以被实现为简单的功能。 使用相同的参数的任何拉姆达和返回类型可以被转换成相同类型的指针和这样的三元:操作者可应用于它们。
例如:非捕获拉姆达:
auto c=[](bool b){return b;};
实现这样的:
class unique_lambda_name_3
{
static bool body(bool b) { return b; }
public:
bool operator () (bool b) const { return body(b); }
operator decltype(&body) () const { return &body; }
} c;
这意味着该行:
auto x = t?[](bool b){return b;}:[](bool b){return !b;};
意思其实这个:
// a typedef to make this more readable
typedef bool (*pfun_t)(bool);
pfun_t x = t?((pfun_t)[](bool b){return b;}):(pfun_t)([](bool b){return !b;});