初始化在三元运算符中捕获lambda

时间:2022-12-03 18:59:03

I wanted to create a lambda in the following way:

我想用以下方式创建一个lambda:

auto l1 = condition ?
          [](){ return true; } :
          [number](){ return number == 123; };

However, I got error:

但是,我收到了错误:

operands to ?: have different types ‘main()::<lambda()>’ and ‘main()::<lambda()>’

Obviously, the types seem to be the same. I thought, that capturing number in only one of lambdas might be a problem, but I get the same error for these:

显然,类型似乎是相同的。我想,只在一个lambda中捕获数字可能是一个问题,但我得到了相同的错误:

//check if capturing number in both lambdas would help
auto l2 = condition ?
          [number](){ return true; } :
          [number](){ return number == 123; };
//maybe the first lambda capture was optimised out? let's make sure:
auto l3 = condition ?
          [number](){ return number != 123; } :
          [number](){ return number == 123; };

I'm aware I can do it other way (below), but I'm wondering what is the cause of this behavior. It was compiled with GCC6.3.1, C++14 enabled.

我知道我可以通过其他方式(下面)这样做,但我想知道这种行为的原因是什么。它是用GCC6.3.1编译的,启用了C ++ 14。

//compiles      
auto l4 = condition ?
          [](const int){ return true; } :
          [](const int number){ return number == 123; };

3 个解决方案

#1


25  

Every lambda expression has unique type (i.e. the closure type, which is a unique unnamed non-union non-aggregate class type), even with the same signature and function body; the compiler just can't deduce the common type of ternary conditional operator for the variable declared by auto, the two closure types are irrelevant at all.

每个lambda表达式都有唯一的类型(即闭包类型,它是一个唯一的未命名的非联合非聚合类类型),即使具有相同的签名和函数体;编译器无法推断出auto声明的变量的三元条件运算符的常见类型,两种闭包类型完全无关。

You can use std::function instead. e.g.

您可以使用std :: function代替。例如

std::function<bool()> l1;
if (condition)
     l1 = [](){ return true; };
else
     l1 = [number](){ return number == 123; };

For l4, note that the lambda-expression with empty capture list could be converted to the corresponding function pointer implicitly. In this case both of them could be converted to the same function pointer type (i.e. bool(*)(int)), which then could be deduced as the common type of ternary conditional operator and the type of l4.

对于l4,请注意带有空捕获列表的lambda表达式可以隐式转换为相应的函数指针。在这种情况下,它们都可以转换为相同的函数指针类型(即bool(*)(int)),然后可以推导出它作为三元条件运算符的常见类型和l4的类型。

#2


10  

If you really want to use the conditional operator you can do it like this:

如果你真的想使用条件运算符,你可以这样做:

auto l1 = condition
          ? std::function<bool()>{[](){ return true; }}
          : std::function<bool()>{[number](){ return number == 123; }};

In C++17 this can be simplified thanks to Class template argument deduction:

在C ++ 17中,由于类模板参数推导,这可以简化:

auto l1 = condition
          ? std::function{[](){ return true; }}
          : std::function{[number](){ return number == 123; }};

#3


4  

A lambda in C++ is an instance of local class implementing functor contract. I mean, operator() etc. And these classes are unrelated and have different types.

C ++中的lambda是实现函子契约的本地类的实例。我的意思是,operator()等。这些类是不相关的,有不同的类型。

Your code is equivalent to

你的代码相当于

struct l1 {
  bool operator () const {
    return true;
  }
};

struct l2 {
  private int number_:
  l2(int number): number_(number){}

  bool operator () const {
    return number_ == 123;
  }
};

int number = ???
auto l3 = condition ? l1 : l2(number);

#1


25  

Every lambda expression has unique type (i.e. the closure type, which is a unique unnamed non-union non-aggregate class type), even with the same signature and function body; the compiler just can't deduce the common type of ternary conditional operator for the variable declared by auto, the two closure types are irrelevant at all.

每个lambda表达式都有唯一的类型(即闭包类型,它是一个唯一的未命名的非联合非聚合类类型),即使具有相同的签名和函数体;编译器无法推断出auto声明的变量的三元条件运算符的常见类型,两种闭包类型完全无关。

You can use std::function instead. e.g.

您可以使用std :: function代替。例如

std::function<bool()> l1;
if (condition)
     l1 = [](){ return true; };
else
     l1 = [number](){ return number == 123; };

For l4, note that the lambda-expression with empty capture list could be converted to the corresponding function pointer implicitly. In this case both of them could be converted to the same function pointer type (i.e. bool(*)(int)), which then could be deduced as the common type of ternary conditional operator and the type of l4.

对于l4,请注意带有空捕获列表的lambda表达式可以隐式转换为相应的函数指针。在这种情况下,它们都可以转换为相同的函数指针类型(即bool(*)(int)),然后可以推导出它作为三元条件运算符的常见类型和l4的类型。

#2


10  

If you really want to use the conditional operator you can do it like this:

如果你真的想使用条件运算符,你可以这样做:

auto l1 = condition
          ? std::function<bool()>{[](){ return true; }}
          : std::function<bool()>{[number](){ return number == 123; }};

In C++17 this can be simplified thanks to Class template argument deduction:

在C ++ 17中,由于类模板参数推导,这可以简化:

auto l1 = condition
          ? std::function{[](){ return true; }}
          : std::function{[number](){ return number == 123; }};

#3


4  

A lambda in C++ is an instance of local class implementing functor contract. I mean, operator() etc. And these classes are unrelated and have different types.

C ++中的lambda是实现函子契约的本地类的实例。我的意思是,operator()等。这些类是不相关的,有不同的类型。

Your code is equivalent to

你的代码相当于

struct l1 {
  bool operator () const {
    return true;
  }
};

struct l2 {
  private int number_:
  l2(int number): number_(number){}

  bool operator () const {
    return number_ == 123;
  }
};

int number = ???
auto l3 = condition ? l1 : l2(number);