Lambda capture causes incompatible operand types error?

前端 未结 1 685
日久生厌
日久生厌 2021-01-02 18:01

Consider the following code:

main()
{
    bool t;
    ...
    std::function f = t ? [](bool b) { return b; } : [](bool b) { return !b; };          


        
1条回答
  •  时光说笑
    2021-01-02 18:28

    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.

    Example: if you write this:

    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 and b have different types and can't be used in the ?: operator.

    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.

    Example: the non-capture lambda:

    auto c=[](bool b){return b;};
    

    is implemented like this:

    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; 
    

    which means that this line:

    auto x = t?[](bool b){return b;}:[](bool b){return !b;};
    

    means actually this:

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

    0 讨论(0)
提交回复
热议问题