[bind] Need Help - Function Composition
Hello all, I'm using boost::bind to get elegant code. Thank the author for the great lib. I'm posting because I ran accross a small problem with the following code. My intention of the code is to find the element of a container with the least abs value of a member (i_). template <typename Arg, typename Result> class less_by_func : public std::binary_function<Arg, Arg, bool> { typedef boost::function<Result(Arg)> fn_t; typedef less_by_func<Arg, Result> self_t; fn_t func_; less_by_func() {} // not open public: less_by_func(const self_t& src) : func_(src.func_) {} explicit less_by_func(const fn_t& func) : func_(func) {} template <typename Arg, typename Result> explicit less_by_func(const less_by_func<Arg, Result>& src) : func_(src.func_) {} bool operator()(const Arg& lhs, const Arg& rhs) const { return func_(lhs) < func_(rhs); } }; // helper function template<typename F> less_by_func<typename F::argument_type, typename F::result_type> make_less_by_func(F func) { return less_by_func<typename F::argument_type, typename F::result_type>(func); } struct A { int i_; A() : i_(0) {} explicit A(int i) : i_(i) {} void set(int i) { i_ = i; } int get() const { return i_; } }; std::vector<A> a_list; a_list.push_back(A(10)); a_list.push_back(A(222)); a_list.push_back(A(-100)); int min_abs = std::min_element(a_list.begin(), a_list.end(), min2max::make_less_by_func( boost::function<int(A)>( boost::bind<int>( std::ptr_fun(&std::abs<int>), boost::bind(&A::i_, _1) ) ) ) )->i_; std::cout << min_abs << std::endl; This code works fine, what I don't understand is why I couldn't remove the explicit construction of a boost::function<int(A)> object and let compiler do the implicit conversion(construction) silently. That means the following code doesn't work: int min_abs = std::min_element(a_list.begin(), a_list.end(), min2max::make_less_by_func( boost::bind<int>( std::ptr_fun(&std::abs<int>), boost::bind(&A::i_, _1) ) ) )->i_; The following code doesn't get compile neither: std::stable_sort(a_list.begin(), a_list.end(), make_less_by_func(boost::bind(&A::i_, _1))); I know a more verbose version like this will also work: int min_abs = std::min_element(a_list.begin(), a_list.end(), boost::bind(std::less(), boost::bind(std::ptr_fun(&std::abs), boost::bind(&A::i_, _1)), boost::bind(std::ptr_fun(&std::abs), boost::bind(&A::i_, _2)) ) )->i_; But I just want the code to be as elegant as possible. :-) My environment is: boost_1_36_0 + VS2003sp1 Thanks for any hints. with best regards Max ------------------------------------------------------------------- 新浪空间——与朋友开心分享网络新生活!(http://space.sina.com.cn/ )
AMDG loadcom wrote:
<snip>
// helper function template<typename F> less_by_func<typename F::argument_type, typename F::result_type> make_less_by_func(F func) { return less_by_func<typename F::argument_type, typename F::result_type>(func); }
<snip>
int min_abs = std::min_element(a_list.begin(), a_list.end(), min2max::make_less_by_func( boost::function<int(A)>( boost::bind<int>( std::ptr_fun(&std::abs<int>), boost::bind(&A::i_, _1) ) ) ) )->i_; std::cout << min_abs << std::endl;
This code works fine, what I don't understand is why I couldn't remove the explicit construction of a boost::function<int(A)> object and let compiler do the implicit conversion(construction) silently. That means the following code doesn't work:
int min_abs = std::min_element(a_list.begin(), a_list.end(), min2max::make_less_by_func( boost::bind<int>( std::ptr_fun(&std::abs<int>), boost::bind(&A::i_, _1) ) ) )->i_;
The function objects created by Boost.Bind are plolymorphic. Thus, since they can be called with multiple different argument types, there is no way for them to provide an argument_type typedef. This means that in template<typename F> less_by_func<typename F::argument_type, typename F::result_type> make_less_by_func(F func); F is deduced as the result of the bind call, and SFINAE prevents this template from matching. The following definition of less_by_func should work better (untested) template<class F> struct less_by_func { typedef bool result_type; F f; template<class T> bool operator()(const T& t1, const T& t2) { return(f(t1) < f(t2)); } }; template<class F> less_by_func<F> make_less_by_func(F f) { less_by_func<F> result = { f }; return(result); } In Christ, Steven Watanabe
participants (2)
-
loadcom
-
Steven Watanabe