Boost logo

Boost Users :

Subject: [Boost-users] [bind] Need Help - Function Composition
From: loadcom (loadcom_at_[hidden])
Date: 2008-12-18 08:54:52


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/ )


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net