...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Here is boost::stl_interfaces::closure
:
/** An invocable consisting of a contained invocable `f`. Calling `operator()` with some argument `t` calls `f(t)` and returns the result. This type is typically used to capture a the result of a call to `bind_back()`. */ template<typename F> struct closure : range_adaptor_closure<closure<F>> { constexpr closure(F f) : f_(f) {} #if BOOST_STL_INTERFACES_USE_CONCEPTS template<typename T> requires std::invocable<F const &, T> #else template< typename T, typename Enable = std::enable_if_t<detail::is_invocable_v<F const &, T>>> #endif constexpr decltype(auto) operator()(T && t) const { return f_((T &&) t); } private: F f_; };
As you can see, it inherits from boost::stl_interfaces::range_adaptor_closure
,
and its only member function is a call operator that forwards to the function
F
it is constructed from. It
exists simply to adapt some function that constructs a particular view to use
in pipe expressions.
adaptor
is slightly different;
it operates essentially just like closure
if you call its operator()
with all arguments necessary to invoke its function F
— it just constructs a view. However, if you pass it all the arguments
but the first, it returns a closure
with all those arguments bound into it:
/** Adapts an invocable `f` as a view adaptor. Calling `operator(args...)` will either: call `f(args...)` and return the result, if `f(args...)` is well-formed; or return `closure(stl_interfaces::bind_back(f, args...))` otherwise. */ template<typename F> struct adaptor { constexpr adaptor(F f) : f_(f) {} // clang-format off template<typename... Args> constexpr auto operator()(Args &&... args) const // clang-format on { #if BOOST_STL_INTERFACES_USE_CONCEPTS if constexpr (std::is_invocable_v<F const &, Args...>) { return f((Args &&) args...); } else { return closure( stl_interfaces::bind_back(f_, (Args &&) args...)); } #else return detail::adaptor_impl< F const &, detail::is_invocable_v<F const &, Args...>, Args...>::call(f_, (Args &&) args...); #endif } private: F f_; };
This allows you to use it both as a view-constructor (e.g. take(range,
3)
),
and as a closure-constructor (e.g. range
| take(3)
).
Important | |
---|---|
Due to the way |