web-dev-qa-db-ja.com

三項演算子でラムダのキャプチャを初期化しています

次の方法でラムダを作成したかったのです。

auto l1 = condition ?
          [](){ return true; } :
          [number](){ return number == 123; };

ただし、エラーが発生しました。

operands to ?: have different types ‘main()::<lambda()>’ and ‘main()::<lambda()>’

明らかに、タイプは同じようです。ラムダの1つだけでnumberをキャプチャすることは問題になるかもしれないと思いましたが、これらについても同じエラーが発生します。

//check if capturing number in both lambdas would help
auto l2 = condition ?
          [number](){ return true; } :
          [number](){ return number == 123; };
//maybe the first lambda capture was optimised out? let's make sure:
auto l3 = condition ?
          [number](){ return number != 123; } :
          [number](){ return number == 123; };

私は他の方法(下記)でそれを行うことができることを知っていますが、この動作の原因は何であるか疑問に思っています。 GCC6.3.1、C++ 14を有効にしてコンパイルされました。

//compiles      
auto l4 = condition ?
          [](const int){ return true; } :
          [](const int number){ return number == 123; };
20
knopers8

すべての ラムダ式 には、同じ署名と関数本体を使用しても、一意の型(つまり、一意の名前のない非ユニオン非集計クラス型であるクロージャ型)があります。コンパイラは、autoで宣言された変数の 三項条件演算子 の一般的な型を推測できません。2つのクロージャ型はまったく関係ありません。

代わりに_std::function_を使用できます。例えば.

_std::function<bool()> l1;
if (condition)
     l1 = [](){ return true; };
else
     l1 = [number](){ return number == 123; };
_

_l4_の場合、キャプチャリストが空のラムダ式は、対応する関数ポインタに暗黙的に変換される可能性があることに注意してください。この場合、両方を同じ関数ポインター型(つまり、bool(*)(int))に変換できます。これは、三項条件演算子の共通型および_l4_型として推定できます。

25
songyuanyao

本当に条件演算子を使用したい場合は、次のように実行できます。

auto l1 = condition
          ? std::function<bool()>{[](){ return true; }}
          : std::function<bool()>{[number](){ return number == 123; }};

C++ 17では、これは クラステンプレート引数の推定 のおかげで簡略化できます。

auto l1 = condition
          ? std::function{[](){ return true; }}
          : std::function{[number](){ return number == 123; }};
11
bolov

C++のラムダは、ファンクターコントラクトを実装するローカルクラスのインスタンスです。つまり、operator()などです。これらのクラスは無関係であり、タイプが異なります。

あなたのコードは同等です

struct l1 {
  bool operator () const {
    return true;
  }
};

struct l2 {
  private int number_:
  l2(int number): number_(number){}

  bool operator () const {
    return number_ == 123;
  }
};

int number = ???
auto l3 = condition ? l1 : l2(number);
4
Minor Threat