微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 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的赋值在捕获失败的情况下有效:

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是不兼容的类型?

解决方法

lambda的类型是“一个唯一的,非联合类类型”,称为闭包类型.每个lambda都实现为一个不同的类型,在声明范围的本地,它有一个重载的operator()来调用函数体.

示例:如果您这样写:

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)说,没有捕获的lambda的闭包类型有一个非显式的公共转换操作符,它将lambda转换为函数指针 – 非闭包可以实现为简单的函数.任何具有相同参数和返回类型的lambda都可以转换为相同类型的指针,因此可以将三元?:运算符应用于它们.

示例:非捕获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;});

原文地址:https://www.jb51.cc/c/117043.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐