Overview

Description

This is a simple, but functional, C++14 lambda library. It takes advantage of the fact that the standard <functional> header already provides std::bind customization points (is_placeholder, is_bind_expression), and function objects such as std::plus, std::greater, std::logical_not, and std::bit_xor, corresponding to arithmetic, relational, logical and bitwise operators.

This allows the library to provide a minimal implementation that still lets expressions such as _1 + 5, _1 % 2 == 0, _1 > _2, or _1 == ' ' || _1 == '\t' to be composed and used as function objects.

For example, _1 + 5 is implemented as std::bind(std::plus<>, _1, 5).

These "lambda" expressions can also be freely combined with std::bind. For example, std::bind( f, _1 ) == std::bind( g, _1 ) and std::bind( f, _1 + _2 ) both work and have the expected behavior.

Usage Examples

Counting the Even Numbers

#include <boost/lambda2.hpp>
#include <algorithm>

using namespace boost::lambda2;

int count_even( int const * first, int const * last )
{
    return std::count_if( first, last, _1 % 2 == 0 );
}

Finding the First Whitespace Character

#include <boost/lambda2.hpp>
#include <algorithm>

char const * find_whitespace( char const * first, char const * last )
{
    using namespace boost::lambda2;

    return std::find_if( first, last,
        _1 == ' ' || _1 == '\t' || _1 == '\r' || _1 == '\n' );
}

Dependencies

None. A single, self-contained header.

Supported Compilers

  • GCC 5 or later with -std=c++14 or above

  • Clang 3.9 or later with -std=c++14 or above

  • Visual Studio 2015, 2017, 2019

Tested on Github Actions and Appveyor.

Revision History

Changes in 1.78.0

  • Added special cases in operator<< and operator>> when the first argument is a stream, to allow std::cout << _1.

  • Added operator->*.

  • Added first, second.

Reference

<boost/lambda2/lambda2.hpp>

Synopsis

namespace boost {
namespace lambda2 {

// placeholders

template<int I> struct lambda2_arg;

inline constexpr lambda2_arg<1> _1{};
inline constexpr lambda2_arg<2> _2{};
inline constexpr lambda2_arg<3> _3{};
inline constexpr lambda2_arg<4> _4{};
inline constexpr lambda2_arg<5> _5{};
inline constexpr lambda2_arg<6> _6{};
inline constexpr lambda2_arg<7> _7{};
inline constexpr lambda2_arg<8> _8{};
inline constexpr lambda2_arg<9> _9{};

// arithmetic operators

template<class A, class B> auto operator+( A && a, B && b );
template<class A, class B> auto operator-( A && a, B && b );
template<class A, class B> auto operator*( A && a, B && b );
template<class A, class B> auto operator/( A && a, B && b );
template<class A, class B> auto operator%( A && a, B && b );
template<class A> auto operator-( A && a );

// relational operators

template<class A, class B> auto operator==( A && a, B && b );
template<class A, class B> auto operator!=( A && a, B && b );
template<class A, class B> auto operator>( A && a, B && b );
template<class A, class B> auto operator<( A && a, B && b );
template<class A, class B> auto operator>=( A && a, B && b );
template<class A, class B> auto operator<=( A && a, B && b );

// logical operators

template<class A, class B> auto operator&&( A && a, B && b );
template<class A, class B> auto operator||( A && a, B && b );
template<class A> auto operator!( A && a );

// bitwise operators

template<class A, class B> auto operator&( A && a, B && b );
template<class A, class B> auto operator|( A && a, B && b );
template<class A, class B> auto operator^( A && a, B && b );
template<class A> auto operator~( A && a );

template<class A, class B> auto operator<<( A && a, B && b );
template<class A, class B> auto operator>>( A && a, B && b );

// additional unary operators

template<class A> auto operator+( A && a );
template<class A> auto operator*( A && a );
template<class A> auto operator++( A && a );
template<class A> auto operator--( A && a );
template<class A> auto operator++( A && a, int );
template<class A> auto operator--( A && a, int );

// compound assignment operators

template<class A, class B> auto operator+=( A && a, B && b );
template<class A, class B> auto operator-=( A && a, B && b );
template<class A, class B> auto operator*=( A && a, B && b );
template<class A, class B> auto operator/=( A && a, B && b );
template<class A, class B> auto operator%=( A && a, B && b );
template<class A, class B> auto operator&=( A && a, B && b );
template<class A, class B> auto operator|=( A && a, B && b );
template<class A, class B> auto operator^=( A && a, B && b );
template<class A, class B> auto operator<<=( A && a, B && b );
template<class A, class B> auto operator>>=( A && a, B && b );

// additional binary operators

template<class A, class B> auto operator->*( A && a, B && b );

// projections

inline constexpr /unspecified/ first{};
inline constexpr /unspecified/ second{};

} // namespace lambda2
} // namespace boost

Placeholders

template<int I> struct lambda2_arg
{
    template<class... A> decltype(auto) operator()( A&&... a ) const noexcept;
    template<class T> auto operator[]( T&& t ) const;
};

lambda2_arg<I> is the type of the library-provided placeholders _I. The standard customization point std::is_placeholder is specialized for it, enabling the use of Lambda2’s placeholders with std::bind.

The placeholders define operator(), which permits their direct use as function objects. E.g. _1(x, y) returns x.

operator[] is also defined to allow expressions like _1[x] or _1[_2].

template<class... A> decltype(auto) operator()( A&&... a ) const noexcept;
  • Returns:

    std::get<std::size_t{I-1}>( std::tuple<A&&…​>( std::forward<A>(a)…​ ) );

template<class T> auto operator[]( T&& t ) const;
  • Returns:

    std::bind( fn, *this, std::forward<T>(t) );, where fn is a function object such that fn(x, y) returns x[y].

Common Requirements

All operators defined in the subsequent sections only participate in overload resolution if at least one of their operands is such that for its unqualified type T, the expression std::is_placeholder<T>::value || std::is_bind_expression<T>::value is true.

Arithmetic Operators

template<class A, class B> auto operator+( A && a, B && b );
  • Returns:

    std::bind( std::plus<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator-( A && a, B && b );
  • Returns:

    std::bind( std::minus<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator*( A && a, B && b );
  • Returns:

    std::bind( std::multiplies<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator/( A && a, B && b );
  • Returns:

    std::bind( std::divides<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator%( A && a, B && b );
  • Returns:

    std::bind( std::modulus<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A> auto operator-( A && a );
  • Returns:

    std::bind( std::negate<>(), std::forward<A>(a) );

Relational Operators

template<class A, class B> auto operator==( A && a, B && b );
  • Returns:

    std::bind( std::equal_to<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator!=( A && a, B && b );
  • Returns:

    std::bind( std::not_equal_to<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator>( A && a, B && b );
  • Returns:

    std::bind( std::greater<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator<( A && a, B && b );
  • Returns:

    std::bind( std::less<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator>=( A && a, B && b );
  • Returns:

    std::bind( std::greater_equal<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator<=( A && a, B && b );
  • Returns:

    std::bind( std::less_equal<>(), std::forward<A>(a), std::forward<B>(b) );

Logical Operators

template<class A, class B> auto operator&&( A && a, B && b );
  • Returns:

    std::bind( std::logical_and<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator||( A && a, B && b );
  • Returns:

    std::bind( std::logical_or<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A> auto operator!( A && a );
  • Returns:

    std::bind( std::logical_not<>(), std::forward<A>(a) );

Bitwise Operators

template<class A, class B> auto operator&( A && a, B && b );
  • Returns:

    std::bind( std::bit_and<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator|( A && a, B && b );
  • Returns:

    std::bind( std::bit_or<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A, class B> auto operator^( A && a, B && b );
  • Returns:

    std::bind( std::bit_xor<>(), std::forward<A>(a), std::forward<B>(b) );

template<class A> auto operator~( A && a );
  • Returns:

    std::bind( std::bit_not<>(), std::forward<A>(a) );

template<class A, class B> auto operator<<( A && a, B && b );
  • Returns:

    std::bind( fn, std::forward<A>(a), std::forward<B>(b) );, where fn is a function object such that fn(x, y) returns x << y.

template<class A, class B> auto operator>>( A && a, B && b );
  • Returns:

    std::bind( fn, std::forward<A>(a), std::forward<B>(b) );, where fn is a function object such that fn(x, y) returns x >> y.

Additional Unary Operators

template<class A> auto operator+( A && a );
  • Returns:

    std::bind( fn, std::forward<A>(a) );, where fn is a function object such that fn(x) returns +x.

template<class A> auto operator*( A && a );
  • Returns:

    std::bind( fn, std::forward<A>(a) );, where fn is a function object such that fn(x) returns *x.

template<class A> auto operator++( A && a );
  • Returns:

    std::bind( fn, std::forward<A>(a) );, where fn is a function object such that fn(x) returns ++x.

template<class A> auto operator--( A && a );
  • Returns:

    std::bind( fn, std::forward<A>(a) );, where fn is a function object such that fn(x) returns --x.

template<class A> auto operator++( A && a, int );
  • Returns:

    std::bind( fn, std::forward<A>(a) );, where fn is a function object such that fn(x) returns x++.

template<class A> auto operator--( A && a, int );
  • Returns:

    std::bind( fn, std::forward<A>(a) );, where fn is a function object such that fn(x) returns x--.

Compound Assignment Operators

template<class A, class B> auto operator@=( A && a, B && b );
  • Returns:

    std::bind( fn, std::forward<A>(a), std::forward<B>(b) );, where fn is a function object such that fn(x, y) returns x @= y.

Additional Binary Operators

template<class A, class B> auto operator->*( A && a, B && b );
  • Returns:

    std::bind( std::forward<B>(b), std::forward<A>(a) );

    Notes:

    This operator is intended to be used with "projection" function objects such as member pointers or member functions taking zero arguments, as in _1->*&X::m or _1->*&X::f.

Projections

inline constexpr /unspecified/ first{};

A function object such that first(x) returns std::get<0>(x).

inline constexpr /unspecified/ second{};

A function object such that second(x) returns std::get<1>(x).

Code Example 1. Using first and second to print out a map
void print( std::map<int, std::string> const & m )
{
    using namespace boost::lambda2;
    std::for_each( m.begin(), m.end(), std::cout << _1->*first << ": " << _1->*second << '\n' );
}

This documentation is copyright 2020, 2021 Peter Dimov and is distributed under the Boost Software License, Version 1.0.