Lambda-Ausdrücke mit einer Capture

Content

Wenn wir Lambda-Ausdrücke mit einem internen Status wie beim Prädikat IsIncreasing wünschen, muss die entsprechende Variable in die capture aufgenommen werden.

Wie lässt sich nun die Verwendung von IsIncreasing durch einen Lambda-Ausdruck ersetzen? Dazu gibt es zwei Ansätze:

Beide Techniken können wir zunächst einsetzen, um das Array mit den Werten 1 bis 100 zu initialisieren.

Hier ist die erste Variante:

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>

int main() {
   /* initialize values and fill it with values 1..100 */
   std::vector<int> values(100);
   int counter;
   std::for_each(values.begin(), values.end(),
      [&](int& value) { value = counter++; });

   /* print values */
   int count = 0;
   for (auto value: values) {
      std::cout << std::setw(4) << value;
      if (++count % 10 == 0) std::cout << std::endl;
   }
   std::cout << std::endl;
}
theon$ g++ -Wall -o init-numbers init-numbers.cpp
theon$ ./init-numbers
   0   1   2   3   4   5   6   7   8   9
  10  11  12  13  14  15  16  17  18  19
  20  21  22  23  24  25  26  27  28  29
  30  31  32  33  34  35  36  37  38  39
  40  41  42  43  44  45  46  47  48  49
  50  51  52  53  54  55  56  57  58  59
  60  61  62  63  64  65  66  67  68  69
  70  71  72  73  74  75  76  77  78  79
  80  81  82  83  84  85  86  87  88  89
  90  91  92  93  94  95  96  97  98  99
theon$ 

So könnte im ersten Ansatz die zweite Variante aussehen:

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>

int main() {
   /* initialize values and fill it with values 1..100 */
   std::vector<int> values(100);
   std::for_each(values.begin(), values.end(),
      [counter = 1](int& value) { value = counter++; });

   /* print values */
   int count = 0;
   for (auto value: values) {
      std::cout << std::setw(4) << value;
      if (++count % 10 == 0) std::cout << std::endl;
   }
   std::cout << std::endl;
}
theon$ g++ -Wall -o init-numbers2 init-numbers2.cpp
init-numbers2.cpp: In lambda function:
init-numbers2.cpp:10:50: error: increment of read-only variable 'counter'
       [counter = 1](int& value) { value = counter++; });
                                                  ^~
theon$ 

Frage und Aufgabe

Vorlage

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <limits>
#include <numeric>
#include <random>
#include <vector>

struct IsIncreasing {
   bool operator()(const int& value) {
      if (value >= last_selected_value) {
	 last_selected_value = value;
	 return true;
      } else {
	 return false;
      }
   }
   int last_selected_value = std::numeric_limits<int>::min();
};

int main() {
   /* initialize values and fill it with shuffled values 1..100 */
   std::vector<int> values(100);
   std::iota(values.begin(), values.end(), 1);
   std::shuffle(values.begin(), values.end(), std::mt19937(2));

   /* select all even values out of it */
   std::vector<int> selected_values;
   std::copy_if(values.begin(), values.end(),
      std::back_inserter(selected_values), IsIncreasing());

   /* print selected values */
   int count = 0;
   for (auto value: selected_values) {
      std::cout << std::setw(4) << value;
      if (++count % 10 == 0) std::cout << std::endl;
   }
   std::cout << std::endl;
}