How to write boost :: lambda functor that returns a new functor

How can I write a lambda expression with two placeholders, one for the called object and one for the function argument, so delivering the called object first returns a unary function.

In the example below, generate should be a lambda expression with the first placeholder for the called object and the second placeholder for the argument. The call to generate(c) should return a unary function in which there is no argument to the function call. In fact, it somehow returns the bool type already, as proven by the static assert.

 #include <boost/lambda/bind.hpp> struct Arg { }; struct Callable : std::unary_function<Arg, bool> { bool operator()( Arg const& a ) const { return true; } }; int main( int argc, const char* argv[] ) { BOOST_AUTO(generate, boost::lambda::bind(boost::lambda::_1, boost::lambda::protect(boost::lambda::_1))); Callable c; BOOST_AUTO(fn, generate(c)); BOOST_STATIC_ASSERT((boost::is_same<BOOST_TYPEOF(fn), bool>::value)); Arg a; bool b = fn(a); _ASSERT(b==true); } 
+4
source share
3 answers

If using Boost.Phoenix, the answer would be a little simpler:

 #include <boost/phoenix/phoenix.hpp> struct callable { typedef bool result_type; bool operator()(int) const { return true; } }; int main() { using phx::bind; using phx::lambda; using phx::arg_names::_1; using phx::local_names::_a; auto generate = lambda(_a = _1)[bind(_a, _1)]; auto fn = generate(callable()); bool b = fn(8); } 

Not that this solution was much more general than the version published by OT. It can be used with any unary function object, no matter what argument, regardless of return type.

The disadvantage is that you need to use the current reference line ...

+4
source

I solved my own problem, although not as elegantly as I had hoped:

  struct FCreateBind { typedef boost::_bi::bind_t<bool, Callable, boost::_bi::list2<boost::arg<1>, boost::arg<2> > > result_type; result_type operator()( Callable const& c ) const { return boost::bind<bool>(c, _1); } }; BOOST_AUTO(generate, boost::bind(FCreateBind(), _1)); BOOST_AUTO(fn, generate(Callable()); bool b = fn(Arg()); 

Of course, in this simple example, I could just write BOOST_AUTO(generate, boost::lambda_1) , since Callable itself is the called object. But I was looking for a way to predefine Callable arguments, so the generated function fn is a null function. This solution would allow me to do this inside FCreateBind .

FCreateBind probably also be FCreateBind , but I still haven't figured out how to define a pointer to the overloaded global function boost::bind .

+1
source

Although I'm not 100% sure, I understand the question, the following code may fit your purpose:

 template< class R > struct FCreateBind { typedef boost::function< R() > result_type; template< class T, class U > result_type operator()( T const& x, U const& y ) const { return boost::bind( x, y ); } }; int main() { BOOST_AUTO( generate, boost::bind( FCreateBind< bool >(), Callable(), _1 ) ); BOOST_AUTO( fn, generate( Arg() ) ); bool b = fn(); } 

Saying maybe this is not as pretty as the questionnaire expects ...
As you mentioned, if we specify one of boost::bind overloads explicitly, FCreateBind not needed. However, as far as I have seen, there seems to be no portable way to indicate overload. So, in this case, probably we should depend on the internal value of boost .
For your information, when testing, you can compile the following code:

 int main() { namespace bb = boost::_bi; // Sorry, for brevity bb::bind_t< bb::unspecified, Callable, bb::list1< bb::value< Arg > > > (*bi)( Callable, Arg ) = boost::bind< bb::unspecified, Callable, Arg >; BOOST_AUTO( generate, boost::bind( bi, Callable(), _1 ) ); BOOST_AUTO( fn, generate( Arg() ) ); bool b = fn(); } 

Hope this helps

0
source

Source: https://habr.com/ru/post/1343007/


All Articles