Lambda捕获导致不兼容的操作数类型错误? [英] Lambda capture causes incompatible operand types error?

查看:97
本文介绍了Lambda捕获导致不兼容的操作数类型错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

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
}

使用Clang 3.1编译时,非捕获lambda的赋值可以执行以下操作,而带有捕获的操作失败:

When compiled with Clang 3.1, the assignment of non-capture lambda works while the one with captures fails:

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
                                          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

为什么捕获

推荐答案

lambda的类型是唯一,非联合类类型称为关闭类型。每个lambda都实现为不同的类型,在声明范围内是局部的,该类型具有重载的operator()来调用函数体。

The type of a lambda is "a unique, non-union class type" called the closure type. Each lambda is implemented as a different type, local to the scope of declaration, which has an overloaded operator () to call the function body.

示例:如果您这样写:

auto a=[t](bool b){return t==b;};
auto b=[t](bool b){return t!=b;};

然后,编译器对此进行编译(或多或少):

Then the compiler compiles this (more or less):

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具有不同的类型,不能在?:运算符中使用。

a and b have different types and can't be used in the ?: operator.

但是,第5.1.2(6)节说,没有捕获的lambda的闭包类型具有非显式的公共转换运算符,该运算符将lambda转换为函数指针-非闭包可以实现为简单功能。具有相同参数和返回类型的任何lambda都可以转换为相同类型的指针,因此可以将三元?:运算符应用于它们。

However, §5.1.2(6) says, that the closure type of a lambda with no capture has a non-explicit, public conversion operator, which converts the lambda to a function pointer - non-closures can be implemented as simple functions. Any lambda with the same argument and return types can be converted to the same type of pointer and so the ternary ?: operator can be applied to them.

示例:非捕获lambda:

Example: the non-capture lambda:

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;});

这篇关于Lambda捕获导致不兼容的操作数类型错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆