cow*_*cow 11 c++ lambda conditional-operator c++11
知道为什么以下代码段无法编译吗?它报错“错误:?的操作数:具有不同的类型”
auto lambda1 = [&](T& arg) {
...
};
auto lambda2 = [&](T& arg) {
...
};
auto lambda = condition ? lambda1 : lambda2;
Run Code Online (Sandbox Code Playgroud)
Evg*_*Evg 12
奇怪的是,如果lambda较少捕获,+则可以使用运算符:
auto lambda1 = [](int arg) { ... };
auto lambda2 = [](int arg) { ... };
auto lambda = condition ? +lambda1 : +lambda2; // This compiles!
lambda(2019);
Run Code Online (Sandbox Code Playgroud)
之所以+可行,是因为它将lambda转换为函数指针,并且两个函数指针具有相同的类型(类似void (*)(int))。
使用GCC和Clang(但不能使用MSVC),+可以省略,lambda仍将转换为函数指针。
Xat*_*ian 11
编译器将各个lambda转换为不同的类。例如,lambda1的定义等效于:
class SomeCompilerGeneratedTypeName {
public:
SomeCompilerGeneratedTypeName(...) { // Capture all the required variables here
}
void operator()(T& arg) const {
// ...
}
private:
// All the captured variables here ...
};
Run Code Online (Sandbox Code Playgroud)
因此,编译器会生成两种不同的类型,从而导致以下类型的不兼容: auto lambda = condition ? lambda1 : lambda2;
以下将起作用:
auto lambda = condition ? std::function<void(T&)>(lambda1) : std::function<void(T&)>(lambda2);
Run Code Online (Sandbox Code Playgroud)
为了强调两个lambda确实是不同的类型,我们可以<typeinfo>从标准库和typeid运算符中使用。Lambda不是多态类型,因此标准保证了'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;
}
Run Code Online (Sandbox Code Playgroud)
程序的输出为(使用GCC 8.3,请参阅Gobolt上的内容):
Z4mainEUlRZ4mainE1TE_/7654536205164302515
Z4mainEUlRZ4mainE1TE0_/10614161759544824066
Run Code Online (Sandbox Code Playgroud)
Pau*_*ans 10
编译器无法确定auto应为哪种类型:
auto lambda = condition ? lambda1 : lambda2;
Run Code Online (Sandbox Code Playgroud)
因为每个lambda都有不同且独特的类型。
一种有效的方法是:
auto lambda = [&](T& arg) {
return (condition ? lambda1(arg) : lambda2(arg));
}
Run Code Online (Sandbox Code Playgroud)
由于2 lambdas(lambda1和lambda2)是2种不同的类型,?:因此无法推断lambdafrom lambda1和的返回类型lambda2。发生这种情况是因为这两个不能相互转换。
它不会编译,因为每个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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
197 次 |
| 最近记录: |