#pragma once #include template struct compose_fn { template constexpr decltype(auto) operator()(Ts &&...ts) const & { return l(r(std::forward(ts)...)); } template constexpr decltype(auto) operator()(Ts &&...ts) & { return l(r(std::forward(ts)...)); } template constexpr decltype(auto) operator()(Ts &&...ts) && { return std::move(l)(std::move(r)(std::forward(ts)...)); } L l; R r; }; template constexpr auto compose(L &&l, R &&r) -> compose_fn, std::decay_t> { return {std::forward(l), std::forward(r)}; } template constexpr auto operator|(compose_fn l, R &&r) { return compose(std::forward(r), std::move(l)); }