Die Boost C++ Bibliotheken

Kapitel 43. Boost.Lambda

Vor C++11 war es notwendig, auf eine Bibliothek wie Boost.Lambda zuzugreifen, um Lambda-Funktionen verwenden zu können. Seit C++11 kann diese Bibliothek als veraltet bezeichnet werden, da Lambda-Funktionen seit dieser Version des Standards Teil der Programmiersprache sind. Arbeiten Sie in einer Entwicklungsumgebung, die C++11 nicht unterstützt, sollten Sie außerdem zuerst einen Blick auf Boost.Phoenix werfen, bevor Sie sich Boost.Lambda zuwenden. Boost.Phoenix ist die neuere Bibliothek, um Lambda-Funktionen ohne C++11 verwenden zu können.

Das Ziel von Lambda-Funktionen ist es, den Code kompakter und damit verständlicher zu machen. Sehen Sie sich dazu Beispiel 43.1 an.

Beispiel 43.1. std::for_each() mit einer Boost.Lambda-Funktion
#include <boost/lambda/lambda.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
  std::vector<int> v{1, 3, 2};
  std::for_each(v.begin(), v.end(),
    std::cout << boost::lambda::_1 << "\n");
}

Boost.Lambda stellt verschiedene Hilfsmittel zur Verfügung, um namenlose Funktionen zu erstellen. Code wird dort angegeben, wo er ausgeführt werden soll, ohne ihn in eine Funktion packen und diese aufrufen zu müssen. So wird mit std::cout << boost::lambda::_1 << "\n" eine Lambda-Funktion definiert, die einen Parameter erwartet und diesen gefolgt von einem Zeilenumbruch in die Standardausgabe schreibt.

Bei boost::lambda::_1 handelt es sich um einen Platzhalter. Mit boost::lambda::_2 und boost::lambda::_3 stellt Boost.Lambda zwei weitere Platzhalter zur Verfügung. Verwenden Sie lediglich boost::lambda::_1, erstellen Sie eine Lambda-Funktion, die einen Parameter erwartet. Verwenden Sie boost::lambda::_2 – zusätzlich zu boost::lambda::_1 oder als einzigen Platzhalter – erwartet die Lambda-Funktion zwei Parameter. Die Signatur der Lambda-Funktion hängt von der höchsten Ziffer der verwendeten Platzhalter ab. Im Beispiel 43.1 darf in der Lambda-Funktion nur der Platzhalter boost::lambda::_1 verwendet werden, weil die Lambda-Funktion an std::for_each() übergeben wird und dieser Algorithmus eine unäre Funktion erwartet.

Beachten Sie, dass Sie die Headerdatei boost/lambda/lambda.hpp einbinden müssen, um Platzhalter verwenden zu können.

Beachten Sie außerdem, dass im Beispiel 43.1 \n und nicht std::endl für einen Zeilenumbruch verwendet wird. Mit std::endl könnte der Code nicht kompiliert werden. Weil der Typ der Lambda-Funktion std::cout << boost::lambda::_1 ein anderer ist als der, den die unäre Template-Funktion std::endl() kennt und erwartet, kann std::endl nicht verwendet werden.

Beispiel 43.2. Eine Boost.Lambda-Funktion mit boost::lambda::if_then()
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/if.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
  std::vector<int> v{1, 3, 2};
  std::for_each(v.begin(), v.end(),
    boost::lambda::if_then(boost::lambda::_1 > 1,
    std::cout << boost::lambda::_1 << "\n"));
}

In der Headerdatei boost/lambda/if.hpp definiert Boost.Lambda mehrere Konstrukte, um if-Kontrollstrukturen in einer Lambda-Funktion zu verwenden. Das einfachste Konstrukt ist die Template-Funktion boost::lambda::if_then(), die zwei Parameter erwartet: Im ersten Parameter wird eine Bedingung überprüft. Ist sie wahr, wird der zweite Parameter ausgeführt. Beide Parameter können wie im Beispiel 43.2 Lambda-Funktionen sein.

Neben boost::lambda::if_then() stellt Boost.Lambda die Template-Funktionen boost::lambda::if_then_else() und boost::lambda::if_then_else_return() zur Verfügung, die beide drei Parameter erwarten. Darüber hinaus gibt es Template-Funktionen für Schleifen, Cast-Operatoren und für throw, um Ausnahmen in Lambda-Funktionen zu werfen. Die zahlreichen von Boost.Lambda definierten Template-Funktionen ermöglichen es, beliebige Lambda-Funktionen zu definieren, die herkömmlichen Funktionen in C++ in nichts nachstehen.