lambda的C++三元赋值
C++ ternary assignment of lambda
知道为什么下面的代码段没有编译吗?它抱怨错误"error:操作数到?:具有不同类型">
auto lambda1 = [&](T& arg) {
...
};
auto lambda2 = [&](T& arg) {
...
};
auto lambda = condition ? lambda1 : lambda2;
奇怪的是,如果Lambda捕获较少,则可以使用运算符+
技巧:
auto lambda1 = [](int arg) { ... };
auto lambda2 = [](int arg) { ... };
auto lambda = condition ? +lambda1 : +lambda2; // This compiles!
lambda(2019);
这是有效的,因为+
将lambda转换为函数指针,并且两个函数指针具有相同的类型(类似于void (*)(int)
(。
使用GCC和Clang(但不使用MSVC(,可以省略+
,lambdas仍将转换为函数指针。
编译器将单个lambda转换为不同的类。例如,lambda1的定义等效于:
class SomeCompilerGeneratedTypeName {
public:
SomeCompilerGeneratedTypeName(...) { // Capture all the required variables here
}
void operator()(T& arg) const {
// ...
}
private:
// All the captured variables here ...
};
因此,编译器生成了两种不同的类型,这导致auto lambda = condition ? lambda1 : lambda2;
的类型不兼容
以下方法可行:
auto lambda = condition ? std::function<void(T&)>(lambda1) : std::function<void(T&)>(lambda2);
为了强调两个lambda确实是不同的类型,我们可以使用标准库中的<typeinfo>
和typeid
运算符。Lambdas不是多态类型,因此标准保证在编译时评估"typeid"运算符。这表明即使RTTI被禁用,以下示例也是有效的:
#include <iostream>
#include <typeinfo>
int main()
{
struct T {
};
auto lambda1 = [&](T& arg) {
return;
};
auto lambda2 = [&](T& arg) {
return;
};
std::cout << typeid(lambda1).name() << "/" << typeid(lambda1).hash_code() << std::endl;
std::cout << typeid(lambda2).name() << "/" << typeid(lambda2).hash_code() << std::endl;
return 0;
}
程序的输出为(GCC 8.3,请参阅Gobolt(:
Z4mainEUlRZ4mainE1TE_/7654536205164302515
Z4mainEUlRZ4mainE1TE0_/10614161759544824066
编译器无法决定auto
应该是什么类型:
auto lambda = condition ? lambda1 : lambda2;
因为每个lambda都有不同且唯一的类型。
其中一种方法是:
auto lambda = [&](T& arg) {
return (condition ? lambda1(arg) : lambda2(arg));
}
它不编译,因为每个lambda都有一个唯一的类型,?:
没有一个公共类型。
你可以将它们包装在std::function<void(T&)>
中,例如
auto lamba1 = [&](T& arg) {
...
};
auto lambda2 = [&](T& arg) {
...
};
auto lambda = condition ? std::function(lambda1) : lambda2; // C++17 class template deduction
由于两个Lambda(lambda1
和lambda2
(是两种不同的类型,?:
无法从lambda1
和lambda2
推导出lambda
的返回类型。之所以会发生这种情况,是因为这两个不可相互转换。
相关文章:
- 为"adjacent"变量赋值时出现问题
- C++中的赋值发生,尽管右侧出现异常
- 用C++中的sscanf赋值
- 为std::string的某个索引赋值
- 重载Singly Linked List中的赋值运算符
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- gtest_使用setargpointee在函数中赋值
- 非常量变量只读位置的赋值
- 使用赋值运算符重载从类中返回jobject
- C++数据文件、数组和计算赋值
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- 全局作用域中函数指针的赋值
- 错误:在为指针赋值时,void值没有被忽略
- 标准库类型的赋值运算符的引用限定符
- lambda的C++三元赋值
- C/C++三元运算符实际上与赋值运算符具有相同的优先级吗
- 三元运算符和赋值运算符
- "error: '=' : left operand must be l-value" ?(在三元中使用赋值时:)
- 三元条件运算符和赋值运算符优先级
- 三元运算符优先级和赋值