[functional] New functor adaptors
Hello, Suppose we want to transform sequence of integers by doubling and adding 5 to each value (x = 2*x + 5 for all x in sequence). If using std::transform, then we need a functor which will for given "x" return "2*x + 5". My question is - is it possible to do it in C++98 style (without lambda expressions), and without writing additional functor class? As I understand, it's not. For doing that we need something like nesting functors into each other. Here we have "std::bind2nd( std::multiplies<int>(), 2 )" functor, and "std::bind2nd( std::plus<int>(), 5 )" functor, which must be nested to provide necessary functionality. I suggest something like "unary_result_translator" functor adapter, which is unary functor itself, and which will apply unary functor to result of another unary functor. The implementation of "unary_result_translator" can be something like this: template< typename Fn1, typename FnTrans > class unary_result_translator { public: typedef typename Fn1::argument_type argument_type; typedef typename FnTrans::result_type result_type; unary_result_translator( const Fn1& fn1, const FnTrans& fn_trans ) : fn1_( fn1 ), fn_trans_( fn_trans ) {} result_type operator()( const argument_type& arg ) const { return fn_trans_( fn1_( arg ) ); } const Fn1& fn1_; const FnTrans& fn_trans_; }; So, we will create our needed functor which converts "x" to "2*x + 5" by this: make_unary_result_translator( std::bind2nd( std::multiplies<int>(), 2 ), std::bind2nd( std::plus<int>(), 5 ) ) Of'course, unary_result_translator can be also used for more complex functors construction. Recently I used it for case-insensitive comparision of strings only with help of ::tolower. Similarly, there can be "binary_result_translator" which is binary functor itself, and which will apply unary functor to result of binary functor. Can that functor adaptors be useful? Or may be there is another way to do such things? Thanks for reading! Best Regards, Tigran Hayrapetyan
On Thu, Sep 12, 2013 at 4:03 PM, Tigran Hayrapetyan
Hello,
Suppose we want to transform sequence of integers by doubling and adding 5 to each value (x = 2*x + 5 for all x in sequence). If using std::transform, then we need a functor which will for given "x" return "2*x + 5". My question is - is it possible to do it in C++98 style (without lambda expressions), and without writing additional functor class?
I think, Boost.Phoenix is what you're looking for.
On 12 September 2013 13:03, Tigran Hayrapetyan wrote:
Hello,
Suppose we want to transform sequence of integers by doubling and adding 5 to each value (x = 2*x + 5 for all x in sequence). If using std::transform, then we need a functor which will for given "x" return "2*x + 5". My question is - is it possible to do it in C++98 style (without lambda expressions), and without writing additional functor class?
std::transform(begin, end, out, boost::bind( std::plus<int>(), 5, boost::bind( std::multiplies<int>(), 2, _1 ) ) );
As I understand, it's not. For doing that we need something like nesting functors into each other. Here we have "std::bind2nd( std::multiplies<int>(), 2 )" functor, and "std::bind2nd( std::plus<int>(), 5 )" functor, which must be nested to provide necessary functionality.
So don't use std::bind2nd, use boost::bind which is superior in every way.
On Thu, Sep 12, 2013 at 4:52 PM, Jonathan Wakely
On 12 September 2013 13:03, Tigran Hayrapetyan wrote:
Hello,
Suppose we want to transform sequence of integers by doubling and adding 5 to each value (x = 2*x + 5 for all x in sequence). If using std::transform, then we need a functor which will for given "x" return "2*x + 5". My question is - is it possible to do it in C++98 style (without lambda expressions), and without writing additional functor class?
std::transform(begin, end, out, boost::bind( std::plus<int>(), 5, boost::bind( std::multiplies<int>(), 2, _1 ) ) );
As I understand, it's not. For doing that we need something like nesting functors into each other. Here we have "std::bind2nd( std::multiplies<int>(), 2 )" functor, and "std::bind2nd( std::plus<int>(), 5 )" functor, which must be nested to provide necessary functionality.
So don't use std::bind2nd, use boost::bind which is superior in every way.
Thanks for your answers. I see it now.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 17/09/13 12:43, Mathieu Champlon wrote:
On 16/09/2013 20:11, Nathan Ridge wrote:
I don't think anything beats the Boost.Phoenix syntax:
std::transform(begin, end, out, 2 * _1 + 5);
To be totally fair it would be :
std::transform(begin, end, out, 2 * boost::phoenix::placeholders::_1 + 5);
I think it's typical to bring the placeholders into the current scope. Ben
participants (6)
-
Andrey Semashev
-
Ben Pope
-
Jonathan Wakely
-
Mathieu Champlon
-
Nathan Ridge
-
Tigran Hayrapetyan