indirecter_unary, indirecter_binary

Hello, because of the lack of a generic adaptor which indirects operations on pointers to the pointees, i.e. sorting a collection of pointers with predicates applying to the pointees, I have come up with two classes, indirecter_unary and indirecter_binary which do exactly that (thanks again to the people from boost users and comp.lang.c++ for assisting me). Both adaptors accept adaptable function objects as well as plain functions. Ex.: inline int plus( int a, int b ) { return a + b; } // ... std::vector<int> vec; // ... std::sort(vec.begin(),vec.end(),indirect_binary(std::less<int>())); // ... std::transform(vec.begin(),vec.end(),vec.begin(),std::ostream_iterator<int>(std::cout,"\n"),indirect_binary(plus)); I have attached the source file. Your feedback would be greatly appreciated. -- Matthias Kaeppler

"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0ff4g$7rm$1@sea.gmane.org...
Ex.: inline int plus( int a, int b ) { return a + b; }
std::vector<int> vec; // ... std::sort(vec.begin(),vec.end(),indirect_binary(std::less<int>())); std::sort(vec.begin(), vec.end(), std::lest<int>()) works just fine. (I used VC7.1) std::transform(vec.begin(),vec.end(),vec.begin(),std::ostream_iterator<int>(std::cout,"\n"),indirect_binary(plus)); I think it also works with out your indirect_binary.
It's VERY VERY similar to std::mem_fun. -- Pavel Chikulaev

Pavel Chikulaev wrote:
"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0ff4g$7rm$1@sea.gmane.org...
Ex.: inline int plus( int a, int b ) { return a + b; }
std::vector<int> vec; // ... std::sort(vec.begin(),vec.end(),indirect_binary(std::less<int>()));
std::sort(vec.begin(), vec.end(), std::lest<int>()) works just fine. (I used VC7.1)
std::transform(vec.begin(),vec.end(),vec.begin(),std::ostream_iterator<int>(std::cout,"\n"),indirect_binary(plus));
I think it also works with out your indirect_binary.
It's VERY VERY similar to std::mem_fun.
-- Pavel Chikulaev
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
My bad, it should read: std::vector<int*> vec; -- Matthias Kaeppler

"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0fsnv$dec$1@sea.gmane.org...
std::vector<int*> vec; Now std::sort(vec.begin(), vec.end(), std::less<int>()) won't work. But I can do it with Boost::Bind: std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
Boost::Bind's solution is much better that yours, because it constists indirector_unary, indirector_binary, indirector_ternary and so on. Pavel Chikulaev

Pavel Chikulaev wrote:
Now std::sort(vec.begin(), vec.end(), std::less<int>()) won't work.
No, why should it? It's a collection of pointers to int, not of int.
But I can do it with Boost::Bind: std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
This looks new to me. What exactly does this do? Sort the container of pointers by applying std::less to the pointees?
Boost::Bind's solution is much better that yours, because it constists indirector_unary, indirector_binary, indirector_ternary and so on.
Pavel Chikulaev
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Matthias Kaeppler

"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0futi$j8m$1@sea.gmane.org...
But I can do it with Boost::Bind: std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
This looks new to me. What exactly does this do? Sort the container of pointers by applying std::less to the pointees?
Boost::Bind's solution is much better that yours, because it constists indirector_unary, indirector_binary, indirector_ternary and so on.
Read boost::bind documentation http://www.boost.org/libs/bind/bind.html. Pavel Chikulaev

Pavel Chikulaev wrote:
"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0futi$j8m$1@sea.gmane.org...
But I can do it with Boost::Bind: std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
This looks new to me. What exactly does this do? Sort the container of pointers by applying std::less to the pointees?
Read boost::bind documentation http://www.boost.org/libs/bind/bind.html.
Have you tried compiling this? Maybe you're thinking of Boost.Lambda. Jonathan

Pavel Chikulaev wrote:
"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0futi$j8m$1@sea.gmane.org...
But I can do it with Boost::Bind: std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
This looks new to me. What exactly does this do? Sort the container of pointers by applying std::less to the pointees?
Boost::Bind's solution is much better that yours, because it constists indirector_unary, indirector_binary, indirector_ternary and so on.
Read boost::bind documentation http://www.boost.org/libs/bind/bind.html.
Pavel Chikulaev
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
That doesn't work for me. std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2)); deref.cpp:154: error: no match for 'operator*' in '*<unnamed>::_1' deref.cpp:154: error: no match for 'operator*' in '*<unnamed>::_2' Am I missing something? -- Matthias Kaeppler

Ooops... You can do it with Boost::Lambda: using namespace boost::lambda; std::sort(vec.begin(), vec.end(), bind(std::less<int>(), *_1, *_2)); Pavel Chikulaev

Matthias Kaeppler <nospam@digitalraid.com> writes:
Pavel Chikulaev wrote:
"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0futi$j8m$1@sea.gmane.org...
But I can do it with Boost::Bind: std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
This looks new to me. What exactly does this do? Sort the container of pointers by applying std::less to the pointees?
Boost::Bind's solution is much better that yours, because it constists indirector_unary, indirector_binary, indirector_ternary and so on. Read boost::bind documentation http://www.boost.org/libs/bind/bind.html. Pavel Chikulaev _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
That doesn't work for me.
std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
deref.cpp:154: error: no match for 'operator*' in '*<unnamed>::_1' deref.cpp:154: error: no match for 'operator*' in '*<unnamed>::_2'
Am I missing something?
No, he should have told you to use the _1 and _2 from the Boost Lambda library. Bind won't handle the *s. -- Dave Abrahams Boost Consulting www.boost-consulting.com

std::sort(vec.begin(), vec.end(), boost::bind(std::less<int>(), *_1, *_2));
deref.cpp:154: error: no match for 'operator*' in '*<unnamed>::_1' deref.cpp:154: error: no match for 'operator*' in '*<unnamed>::_2'
Am I missing something?
If I remember correctly, the Boost.Bind placeholders (_1, _2, etc) work for non-operator usage. The Boost.Lambda placeholders support all the operator overloads. kalin

Hi Matthias, "Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0ff4g$7rm$1@sea.gmane.org... | Hello, | | because of the lack of a generic adaptor which indirects operations on | pointers to the pointees, i.e. sorting a collection of pointers with | predicates applying to the pointees, I have come up with two classes, | indirecter_unary and indirecter_binary which do exactly that (thanks | again to the people from boost users and comp.lang.c++ for assisting | me). Both adaptors accept adaptable function objects as well as plain | functions. these classes are useful when we need to use a class; boost.bind won't work since we don't know what type it returns. I have been playing with similar functionality for Boost.Pointer Container because the ptr_set class needs it. I have a question, though. I'm thinking, what is the benefit of your approach compared to template< class Fun > class indirect_fun { Fun fun; public: typedef typename result_of<Fun>::type result; indirect_fun( Fun f ) : fun(f) { } template< class T > result operator( T* r ) const { return fun( *r ); } template< class T, class U > result operator( T* r, U* r2 ) const { return fun( *r, *r2 ); } // etc }; br -Thorsten

Thorsten Ottosen wrote:
Hi Matthias,
"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0ff4g$7rm$1@sea.gmane.org... | Hello, | | because of the lack of a generic adaptor which indirects operations on | pointers to the pointees, i.e. sorting a collection of pointers with | predicates applying to the pointees, I have come up with two classes, | indirecter_unary and indirecter_binary which do exactly that (thanks | again to the people from boost users and comp.lang.c++ for assisting | me). Both adaptors accept adaptable function objects as well as plain | functions.
these classes are useful when we need to use a class; boost.bind won't work since we don't know what type it returns.
I have been playing with similar functionality for Boost.Pointer Container because the ptr_set class needs it.
I have a question, though. I'm thinking, what is the benefit of your approach compared to
template< class Fun > class indirect_fun { Fun fun; public: typedef typename result_of<Fun>::type result;
indirect_fun( Fun f ) : fun(f) { }
template< class T > result operator( T* r ) const { return fun( *r ); }
template< class T, class U > result operator( T* r, U* r2 ) const { return fun( *r, *r2 ); }
// etc };
br
-Thorsten
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
There are several problems with this template. First, it's not an "Adaptable Binary Function" or "Adaptable Unary Function", because it fails to provide the required typedefs result_type and argument_type, and result_type and first_argument_type, second_argument_type respectively. Second, it might fail to compile when Fun takes arguments by reference. I had problems at this part, that's why I used the boost type traits library to remove any references on the type first, and only work on "raw" const-pointers. Third, (correct me if I'm wrong, I haven't used it before), as far as I understand, the result_of class template won't work if you instantiate your template with a plain function. Instead, boost::unary_traits and boost::binary_traits take care of the right typedefs if you want your adaptor to work with both functors and functions. -- Matthias Kaeppler

"Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0h8mf$v50$1@sea.gmane.org... | Thorsten Ottosen wrote: | > Hi Matthias, | > | > I have been playing with similar functionality for Boost.Pointer Container | > because the ptr_set class needs it. | > | > I have a question, though. I'm thinking, what is the benefit of your approach | > compared to | > | > template< class Fun > | > class indirect_fun | > { | > Fun fun; | > public: | > typedef typename result_of<Fun>::type result; | > | > indirect_fun( Fun f ) : fun(f) | > { } | > | > template< class T > | > result operator( T* r ) const | > { return fun( *r ); } | > | > template< class T, class U > | > result operator( T* r, U* r2 ) const | > { return fun( *r, *r2 ); } | > | > // etc | > }; | There are several problems with this template. | | First, it's not an "Adaptable Binary Function" or "Adaptable Unary | Function", because it fails to provide the required typedefs result_type | and argument_type, and result_type and first_argument_type, | second_argument_type respectively. yes, that is true. | Second, it might fail to compile when Fun takes arguments by reference. | I had problems at this part, that's why I used the boost type traits | library to remove any references on the type first, and only work on | "raw" const-pointers. well, that doesn't happen when operator()() is templated. | Third, (correct me if I'm wrong, I haven't used it before), as far as I | understand, the result_of class template won't work if you instantiate | your template with a plain function. yep, it should be funtion_traits<Fun>::result_type; but my question is this: given that these typedefs are added to the template, what is the benefit of having 2 classes instead of 1? -Thorsten

Thorsten Ottosen wrote:
but my question is this: given that these typedefs are added to the template, what is the benefit of having 2 classes instead of 1?
Well, I guess for the same reason that unary_traits and binary_traits are 2 classes instead of one. :) You never need both at the same time, so one of your operator() is always superfluous. Even from the standpoint of intuitivity of usage, I thought it'd be better to separate them into two classes. But maybe that's just me. -- Matthias Kaeppler

Matthias Kaeppler <nospam@digitalraid.com> writes:
Thorsten Ottosen wrote:
Hi Matthias, "Matthias Kaeppler" <nospam@digitalraid.com> wrote in message news:d0ff4g$7rm$1@sea.gmane.org... | Hello, | | because of the lack of a generic adaptor which indirects operations on | pointers to the pointees, i.e. sorting a collection of pointers with | predicates applying to the pointees, I have come up with two classes, | indirecter_unary and indirecter_binary which do exactly that (thanks | again to the people from boost users and comp.lang.c++ for assisting | me). Both adaptors accept adaptable function objects as well as plain | functions. these classes are useful when we need to use a class; boost.bind won't work since we don't know what type it returns. I have been playing with similar functionality for Boost.Pointer Container because the ptr_set class needs it. I have a question, though. I'm thinking, what is the benefit of your approach compared to template< class Fun > class indirect_fun { Fun fun; public: typedef typename result_of<Fun>::type result; indirect_fun( Fun f ) : fun(f) { } template< class T > result operator( T* r ) const { return fun( *r ); } template< class T, class U > result operator( T* r, U* r2 ) const { return fun( *r, *r2 ); } // etc };
This is too specific for Matthias' purposes (doesn't work on containers of iterators or smart pointers). Maybe something like: template< class Fun > struct indirect_fun { indirect_fun( Fun f ) : fun(f) { } template< class T > typename result_of<Fun(typename pointee<T>::type)>::type operator()( T const& r ) const { return fun( *r ); } template< class T, class U > typename result_of< Fun( typename pointee<T>::type, typename pointee<U>::type, )>::type operator( T const& r, U const& r2 ) const { return fun( *r, *r2 ); } // etc private: Fun fun; };
br -Thorsten _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
There are several problems with this template.
First, it's not an "Adaptable Binary Function" or "Adaptable Unary Function", because it fails to provide the required typedefs result_type and argument_type, and result_type and first_argument_type, second_argument_type respectively.
IMO that's not very important. (Statically) polymorphic function objects like the above are increasingly common, and your design doesn't allow them to be adapted. For example: struct add { template <class T> T operator()(T x, T y) const { return x+y; } }; Now take a container of pointers to T and add the Ts up using std::accumulate and add, above.
Second, it might fail to compile when Fun takes arguments by reference.
?? Why would it fail?
I had problems at this part, that's why I used the boost type traits library to remove any references on the type first, and only work on "raw" const-pointers.
Third, (correct me if I'm wrong, I haven't used it before), as far as I understand, the result_of class template won't work if you instantiate your template with a plain function.
Accounted for above. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1xar33ps.fsf@boost-consulting.com... | Matthias Kaeppler <nospam@digitalraid.com> writes: | | > Thorsten Ottosen wrote: | >> template< class Fun > | >> class indirect_fun | >> { | >> Fun fun; | This is too specific for Matthias' purposes (doesn't work on | containers of iterators or smart pointers). Maybe something like: | | template< class Fun > | struct indirect_fun | { | indirect_fun( Fun f ) : fun(f) | { } | | template< class T > | typename | result_of<Fun(typename pointee<T>::type)>::type | operator()( T const& r ) const | { return fun( *r ); } yeah, this is good stuff, mind if I borrow it? -Thorsten

Thorsten Ottosen wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1xar33ps.fsf@boost-consulting.com...
Matthias Kaeppler <nospam@digitalraid.com> writes:
Thorsten Ottosen wrote:
template< class Fun > class indirect_fun { Fun fun;
This is too specific for Matthias' purposes (doesn't work on containers of iterators or smart pointers). Maybe something like:
template< class Fun > struct indirect_fun { indirect_fun( Fun f ) : fun(f) { }
template< class T > typename result_of<Fun(typename pointee<T>::type)>::type operator()( T const& r ) const { return fun( *r ); }
yeah, this is good stuff, mind if I borrow it?
Wouldn't it be a good thing to use the full result_of "protocol" as specified in the docs (and more specifically in the N1454) ? Regards // Fredrik Blomqvist

"Fredrik Blomqvist" <fredrik_blomqvist@home.se> writes:
Thorsten Ottosen wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1xar33ps.fsf@boost-consulting.com...
template< class Fun > struct indirect_fun { indirect_fun( Fun f ) : fun(f) { }
template< class T > typename result_of<Fun(typename pointee<T>::type)>::type operator()( T const& r ) const { return fun( *r ); }
yeah, this is good stuff, mind if I borrow it?
Wouldn't it be a good thing to use the full result_of "protocol" as specified in the docs (and more specifically in the N1454) ?
Namely what? Am I missing some cv qualification and references? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Fredrik Blomqvist" <fredrik_blomqvist@home.se> writes:
Thorsten Ottosen wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1xar33ps.fsf@boost-consulting.com...
template< class Fun > struct indirect_fun { indirect_fun( Fun f ) : fun(f) { }
template< class T > typename result_of<Fun(typename pointee<T>::type)>::type operator()( T const& r ) const { return fun( *r ); }
yeah, this is good stuff, mind if I borrow it?
Wouldn't it be a good thing to use the full result_of "protocol" as specified in the docs (and more specifically in the N1454) ?
Namely what? Am I missing some cv qualification and references?
That indirect_fun would benefit from supplying the nested result<> template that result_of uses to deduce return types. Basically this is what I labelled the result_of "protocol" (for function objects). [from docs/1454 by Douglas Gregor] "When F is a class type with a member type result_type, result_of<F(T1, T2, ..., TN)> is F::result_type. Otherwise, result_of<F(T1, T2, ..., TN)> is F::result<F(T1, T2, ..., TN)>::type when N > 0 or void when N = 0." Regards // Fredrik Blomqvist

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1xar33ps.fsf@boost-consulting.com... | Matthias Kaeppler <nospam@digitalraid.com> writes: | | > Thorsten Ottosen wrote:
| >> template< class Fun > | >> class indirect_fun | >> { | >> Fun fun;
| This is too specific for Matthias' purposes (doesn't work on | containers of iterators or smart pointers). Maybe something like: | | template< class Fun > | struct indirect_fun | { | indirect_fun( Fun f ) : fun(f) | { } | | template< class T > | typename | result_of<Fun(typename pointee<T>::type)>::type | operator()( T const& r ) const | { return fun( *r ); }
yeah, this is good stuff, mind if I borrow it?
Be my guest. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
template< class Fun > struct indirect_fun { indirect_fun( Fun f ) : fun(f) { }
template< class T > typename result_of<Fun(typename pointee<T>::type)>::type operator()( T const& r ) const { return fun( *r ); }
template< class T, class U > typename result_of< Fun( typename pointee<T>::type, typename pointee<U>::type, )>::type operator( T const& r, U const& r2 ) const { return fun( *r, *r2 ); }
// etc private: Fun fun; };
Now, what exactly is better about this template over the one I posted? Sorry for my ignorance, but I just don't get the point. For example, it looks like this template doesn't handle the reference-to-reference problem. And what is pointee<T>? Is this a boost template? Regards, Matthias Kaeppler

David Abrahams wrote:
Matthias Kaeppler <nospam@digitalraid.com> writes:
Your feedback would be greatly appreciated.
Here's mine: you should not include boost/type_traits.hpp. Use the specific granular headers you need.
Okay, thanks. But what about the overall class design? Is there still unnecessary overhead or even examples where they don't work as supposed? -- Matthias Kaeppler

David Abrahams wrote:
Matthias Kaeppler <nospam@digitalraid.com> writes:
Here's mine: you should not include boost/type_traits.hpp. Use the specific granular headers you need.
[ see http://tinyurl.com/6amen ] - haven't you told 'em ;-) ? Cheers, Tobias

"Tobias Schwinger" <tschwinger@neoscientists.org> wrote in message news:d0i1qr$h5v$1@sea.gmane.org... | David Abrahams wrote: | > Matthias Kaeppler <nospam@digitalraid.com> writes: | > | > Here's mine: you should not include boost/type_traits.hpp. Use the | > specific granular headers you need. | > | | [ see http://tinyurl.com/6amen ] - haven't you told 'em ;-) ? this shows the algorithm header...what has it got to do with this? -Thorsten

Thorsten Ottosen wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote in message news:d0i1qr$h5v$1@sea.gmane.org... | David Abrahams wrote: | > Matthias Kaeppler <nospam@digitalraid.com> writes: | > | > Here's mine: you should not include boost/type_traits.hpp. Use the | > specific granular headers you need. | > | | [ see http://tinyurl.com/6amen ] - haven't you told 'em ;-) ?
this shows the algorithm header...what has it got to do with this?
It shows Adobe's algorithm header with #include <boost/type_traits.hpp>. -- Tobias

Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
Matthias Kaeppler <nospam@digitalraid.com> writes: Here's mine: you should not include boost/type_traits.hpp. Use the specific granular headers you need.
[ see http://tinyurl.com/6amen ] - haven't you told 'em ;-) ?
Haven't you? ;-) -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
David Abrahams wrote:
Matthias Kaeppler <nospam@digitalraid.com> writes: Here's mine: you should not include boost/type_traits.hpp. Use the specific granular headers you need.
[ see http://tinyurl.com/6amen ] - haven't you told 'em ;-) ?
Haven't you? ;-)
Pay me for consulting and I will ;-) ! Besides kidding, I shouldn't - maybe they use precompiled headers. Btw. didn't notice TinyURL is well versed in the bible, before... -- Tobias

Tobias Schwinger wrote:
David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
[ see http://tinyurl.com/6amen ] - haven't you told 'em ;-) ?
Btw. didn't notice TinyURL is well versed in the bible, before...
Now that they're up to four-letter words, I hope they have filtering in place. Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> writes:
Tobias Schwinger wrote:
David Abrahams wrote:
Tobias Schwinger <tschwinger@neoscientists.org> writes:
[ see http://tinyurl.com/6amen ] - haven't you told 'em ;-) ?
Btw. didn't notice TinyURL is well versed in the bible, before...
Now that they're up to four-letter words, I hope they have filtering in place.
I'm afraid not. Try 6f... you know. -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (8)
-
David Abrahams
-
Fredrik Blomqvist
-
Jonathan Turkanis
-
kalin
-
Matthias Kaeppler
-
Pavel Chikulaev
-
Thorsten Ottosen
-
Tobias Schwinger