与三元运算不兼容的操作数

时间:2018-04-01 09:44:15

标签: c++ c++11

我在编写lambda表达式时偶然发现了一个奇怪的问题。这是代码:

domainlogic

我认为可以使用的原始代码是 C 。他们基本上都做同样的事情。 GCC和Clang(Atom& finter使用)产生:

  • 什么有效:A,B
  • 什么不是:C,D

说操作数不是同一类型。这对我来说很奇怪。我的假设是每个lambda表达式都有一个独特的类型,但这并不能解释展览B的作用。为什么不在B工作时不工作?只是编译器在确定lambda类型时做出了疯狂的猜测吗?

所以,我的问题是:

  • 为什么B工作???
  • 每个lambda表达式都有自己独特的类型,需要进行转换(然后再来一次,B怎么运行?)?
  • 这是一个错误吗?

为了澄清,#if 1 /* exhibit A */ const auto giveup = this->__randomGiveUp(); auto evtFunc = [this, giveup]() { this->__acquireLock(); if (giveup) { this->__releaseLock(); } }; #endif #if 0 /* exhibit B */ auto evtFunc = this->__randomGiveUp() ? (std::function<void()>)[this]() { this->__acquireLock(); this->__releaseLock(); } : [this]() { this->__acquireLock(); }; #endif #if 0 /* exhibit C */ auto evtFunc = this->__randomGiveUp() ? [this]() { this->__acquireLock(); this->__releaseLock(); } : [this]() { this->__acquireLock(); }; #endif #if 0 /* exhibit D */ std::function<void()> evtFunc = this->__randomGiveUp() ? [this]() { this->__acquireLock(); this->__releaseLock(); } : [this]() { this->__acquireLock(); }; #endif this->__eventCtx.addEvent(this->__tickStart + this->__randomAcquireDelay(), evtFunc); 的返回类型是bool。

2 个答案:

答案 0 :(得分:2)

每个lambda函数都有自己独特的类型。这就是C和D不起作用的原因:第二个和第三个操作数之间没有转换。如果两个操作数都不属于该类型,则C ++不会尝试转换为某些不相关的类型,例如std::function

这解释了为什么B工作:第二个运算符的类型为std::function<>,第三个操作数的lambda函数类型可以通过std::function构造函数转换为第二个操作数的类型。

答案 1 :(得分:0)

  

每个lambda表达式都有自己独特的类型,需要进行转换(然后再说一次B怎么运行?)

是的,他们是。 lambda表达式的结果是未命名类型的函数对象。你必须把它包装成std::function或一些可以从lambda初始化的类似模板,以免lambda表达式是无捕获的(空捕获列表)。后者可以转换为函数指针,因此可以与三元一起使用(这里的Microsoft编译器可能会认为不同,因为它有几个函数类型的中间指针,在调用约定方面不同):

double (*square)(double)  = [](double a)->double { return a*a; };

auto foo = (square) ? [](double a)->double { return a*a; } :
            [](double a)->double { return a*a*a; };

B变体似乎通过三元运算符的机制隐式地(或者更确切地说,使用适当的构造函数创建std::function对象)执行第二个操作数的转换。您可以在此处查看:Ternary operator of different types