С++ 11 lambda expression - Capture vs Argument Passing

Рассмотрим функцию сравнения положительных целых чисел; сама функция использует лямбда для выполнения задания.

// Pass n1, n2 by value to the lambda.
bool Compare(int n1, int n2) {
    return [](int n1, int n2) { return n1 > n2; };
}

Вышеприведенный фрагмент компилируется отлично; хотя Compare() всегда возвращает true;

Однако следующий код даже не скомпилируется -

// capturing values
bool Compare(int n1, int n2) {
    return [n1, n2]() -> bool { return n1 > n2; };
}

и возвращает ошибку

lambda.cpp:48:46: error: cannot convert 'Compare(int, int)::__lambda2' to 'bool' in   return
  return [n1, n2]() -> bool { return n1 > n2; };

Вопрос

Возможно, это не намеренное использование ввода лямбда в С++, все еще...

  • Почему первый всегда возвращает true?
  • Почему второй не удается скомпилировать?

Ответ 1

Почему первый всегда возвращает true?

Lambdas распадается на указатели функций, которые неявно конвертируются в логические значения (всегда true для lambdas, потому что указатель никогда не является нулевым).

Почему второй не удается скомпилировать?

Lambdas, которые захватывают что-либо, не имеют этого преобразования в указатель функции (как бы это состояние прошло?)

Если вы должны использовать лямбда:

Назовите его:

return [](int n1, int n2) { return n1 > n2; }(n1, n2); //notice the () to call it

Или ваш второй способ, который имеет больше смысла, но не так сильно, как просто return n1 > n2:

return [=] { return n1 > n2; }(); //= captures everything used by value
                                  //-> bool and parameter list are redundant

Наконец, стоит отметить, что std::greater, в <functional>, уже делает это:

std::sort(…, std::greater<int>()); //std::greater<> in C++14