Header lexy/callback/fold.hpp

Sinks that fold over the items.

Sink lexy::fold

lexy/callback/fold.hpp
namespace lexy
{
    template <typename T, typename Arg = T, typename ... Op>
    constexpr sink<> auto fold(Arg&& init, Op&& ... op);
}

Sink that folds over all arguments.

When sink() is called, creates a T result by constructing it from T(init), if that is well-formed, and invoking init() otherwise. Every time the sink callback is invoked, folds the arguments via result = std::invoke(make-overloaded(op…​), std::move(result), args…​). The final value of result is returned by finish().

Example 1. Parse a list of points and sum the x components
struct production
{
    static constexpr auto whitespace = dsl::ascii::space;

    static constexpr auto rule = [] {
        // An item is a point (x, y)
        auto integer = dsl::integer<int>;
        auto item    = dsl::parenthesized(dsl::twice(integer, dsl::sep(dsl::comma)));

        return dsl::list(item, dsl::sep(dsl::comma));
    }();

    // Sum the x components of the points.
    static constexpr auto value
        = lexy::fold<int>(0, [](int current, int x, int) { return current + x; });
};
Note
Usually with fold algorithms, op is a binary function. As the operator() of the sink callback can take arbitrary arguments, this is not necessarily the case here. The first argument will always be the current result, all other arguments are received from the sink callback.
Tip
Use lexy::callback  to use fold as a callback.

Sink lexy::fold_inplace

lexy/callback/fold.hpp
namespace lexy
{
    template <typename T, typename Arg = T, typename ... Op>
    constexpr sink<> auto fold_inplace(Arg&& init, Op&& ... op);
}

Sink that folds over all arguments, modifying the current value.

When sink() is called, creates a T result by constructing it from T(init), if that is well-formed, and invoking init() otherwise. Every time the sink callback is invoked, folds the arguments via std::invoke(make-overloaded(op…​), result, args…​), expecting that op modifies result to the new value. The final value of result is returned by finish().

Example 2. Parse a list of numbers, but store them in reverse
struct production
{
    static constexpr auto whitespace = dsl::ascii::space;

    static constexpr auto rule = [] {
        auto integer = dsl::integer<int>;

        return dsl::list(integer, dsl::sep(dsl::comma));
    }();

    // Construct a `std::deque` in reverse order.
    static constexpr auto value
        = lexy::fold_inplace<std::deque<int>>(std::initializer_list<int>{},
                                              [](auto& deque, int i) { deque.push_front(i); });
};
Note
lexy::fold accepts operator+, lexy::fold_inplace accepts operator+=.

Sink lexy::count

lexy/callback/fold.hpp
namespace lexy
{
    constexpr sink<> auto count =
    = fold_inplace<std::size_t>(0, [](std::size_t& result, auto&&...) { ++result; });
}

Counts the number of invocation of the sink callback.

It is entirely equivalent to the lexy::fold_inplace call specified above.

See also