cpp-expression
is a single-header, header-only library, offering Boost.Lambda-like syntax for declaring lambda expressions:
std::for_each(begin(v), end(v), std::cout << _1);
cpp-expression
builds up on the idea of expression templates. The library introduces three fundamental types:
expr::constant
expr::variable
expr::placeholder
Any unary or binary operation, involving expressions of the aforementioned types, automatically becomes a delayed function, that is:
std::cout << _1;
is not executed until a function call operator is applied:
auto lambda = std::cout << _1;
lambda(3.14f); // prints 3.14
expr::_1
, expr::_2
, ...
, expr::_7
(or just _1
, _2
) are so-called placeholders that represent an actual argument from a delayed function call, and themselves are delayed functions, that is:
_1('a', 'b', 'c', 'd'); // returns 'a'
_2('a', 'b', 'c', 'd'); // returns 'b'
_3('a', 'b', 'c', 'd'); // returns 'c'
_4('a', 'b', 'c', 'd'); // returns 'd'
expr::variable
holds a reference to the wrapped object and itself is a delayed function, delegating any operation to that object:
int i = 0;
auto inc = ++expr::variable(i);
inc(); // i now equals 1
inc(); // i now equals 2
expr::constant
holds a copy of the passed object and itself is a delayed function, useful to overcome the problem of operator precedence:
auto lambda = std::cout << expr::constant('\n') << _1;
Had expr::constant
not been used, the compiler would first execute std::cout << '\n'
, printing a new line character to the standard output, and then construct a delayed function of the form std::cout << _1
(that is, without a leading new line character).
Hint: When in doubt, call the
expr::expressify(e)
helper function.
cpp-expression
allows short-circuit evaluation of operands, making the below code safe:
(_1 != nullptr && *_1 == 42)(nullptr);
#include "expression.hpp"
expr::variable(a)++, std::cout << expr::constant('\n') << expr::_1 << expr::_2;
using namespace expr::placeholders;
expr::variable(a)++, std::cout << expr::constant('\n') << _1 << _2;
using namespace expr;
variable(a)++, std::cout << constant('\n') << _1 << _2;
std::for_each(begin(v), end(v), std::cout << _1 << '\n');
std::sort(begin(v), end(v), _1 > _2);
std::sort(begin(v), end(v), (_1->*&A::foo)() > (_2->*&A::foo)());
std::any_of(begin(ptrs), end(ptrs), _1 != nullptr && *_1 == 5);
std::transform(begin(a), end(a), begin(b), begin(c), _1 + _2);
int sum = 0;
std::for_each(begin(v), end(v), sum += _1);
std::for_each(begin(a), end(a), std::cout << constant('\n') << _1);
std::for_each(begin(indices), end(indices), ++variable(array)[_1]);
void foo(int i, char c);
bind(&foo, _2, _1)('a', 5);
struct A { int i; } a;
auto lambda = (_1->*&A::i) = _2;
lambda(a, 42);
struct A { int foo(char, float); } a;
auto lambda = (_1->*&A::foo)(_2, 3.14f);
lambda(a, 'a');
SPDX-License-Identifier: MIT
See LICENSE for details.