Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This version of Boost is under active development. You are currently in the master branch. The current version is 1.89.0.
As we saw in the previous section, you can use boost::stl_interfaces::bind_back() in combination with closure
to make closure objects that use the pipe syntax. std::bind_back() is an addition to C++23 that is designed
to make constructing view adaptors easier.
In some cases, you might have a view adaptor for which adaptor
is too simple. For instance, let's say you have a view adaptor foo that can be parameterized in more than
one way. Perhaps range |
foo(a, b) is a valid use, but so is range
| foo(b,
c, d). If this
is the case, adaptor's all-but-one
argument binding is no help.
If you have a view adaptor like this, you should re-introduce an impl class like we saw in the all() example,
and construct closures from
bind_back()
expressions as needed:
template<typename R> struct foo_view { // etc. template<typename R2> requires std::is_same_v<std::remove_reference_t<R2>, R> foo_view(R2 &&, int, std::string); template<typename R2> requires std::is_same_v<std::remove_reference_t<R2>, R> foo_view(R2 &&, std::string, int, double); // etc. }; struct foo_impl { // These just directly construct the view from the full set of arguments. template<typename R> auto operator()(R && r, int i, std::string s) const { return foo_view((R &&)r, i, std::move(s)); } template<typename R> auto operator()(R && r, std::string s, int i, double d) const { return foo_view((R &&)r, std::move(s), i, d); } // This one binds *this, i, and s into a bind-expression (which is an // invocable object), and then uses that invocable to construct a // closure. When the closure is called with a range r, it forwards that // range arg to the bind-expression, which calls (*this)(r, i, // std::move(s)). auto operator()(int i, std::string s) const { return boost::stl_interfaces::closure( boost::stl_interfaces::bind_back(*this, i, std::move(s))); } // Works just like the overload immediately above, but with a // different set of parameters. auto operator()(std::string s, int i, double d) const { return boost::stl_interfaces::closure( boost::stl_interfaces::bind_back(*this, std::move(s), i, d)); } }; inline constexpr foo_impl foo;
With these definitions, you can use foo
as we discussed earlier; range | foo(42, "bar") and range
| foo("bar", 42,
3.14)
are both well-formed, and do what you'd expect.