dimanche 1 avril 2018

Incompatible operands to ternary op

I stumbled upon a strange problem when writing lambda expressions. Here's the code:

#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);

My original code that I thought would work was C. They all basically do the same thing. GCC and Clang(which Atom's linter uses) produces:

  • What works: A, B
  • What doesn't: C, D

Saying the operands are not the same type. This is strange to me. My assumption was that every lambda expression is given a unique type, but that doesn't explain the exhibit B, which works. And why doesn't D work while B does? Is it just that the compiler make wild guesses when determining lambda types?

So, my question is:

  • Why B work???
  • Are lambda expressions each have their own unique type and need to be cast(then again, how come B works??)?
  • Is this a bug?

For clarification, the return type of this->__randomGiveUp() is bool.

Aucun commentaire:

Enregistrer un commentaire