知道为什么以下代码段无法编译吗?它报错“错误:?的操作数:具有不同的类型”

  auto lambda1 = [&](T& arg) {
      ...
  };
  auto lambda2 = [&](T& arg) {
      ...
  };
  auto lambda = condition ? lambda1 : lambda2;

最佳答案

编译器会将各个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运算符。 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;
}

该程序的输出为(使用GCC 8.3,see on Gobolt):
Z4mainEUlRZ4mainE1TE_/7654536205164302515
Z4mainEUlRZ4mainE1TE0_/10614161759544824066

07-24 13:59