Member variable comparator factory

Discussion in 'C++' started by Juha Nieminen, Feb 23, 2010.

  1. Assume you have some kind of struct with several member variables. For
    the same of simplicity, let's assume that your struct is like:

    struct Info
    {
    str::string name;
    int age;
    };

    Now, suppose you have, for example, a vector of objects of type Info,
    and you would like to be able to sort the vector either by name or by age.
    Bummer, you'll have to write two comparators for this. However, wouldn't
    it be nice if you could just do something like this:

    // Sort the array by name:
    std::sort(array.begin(), array.end(),
    makeMemberComparator(&Info::name);

    or

    // Sort the array by age:
    std::sort(array.begin(), array.end(),
    makeMemberComparator(&Info::age);

    That way you wouldn't have to write a new comparator function every time
    you need to sort by some member variable of some struct.

    Well, it is very possible to implement a 'makeMemberComparator()' like
    above. It happens like this:

    //--------------------------------------------------------------------
    template<typename Object_t, typename Var_t>
    class MemberVarComparator
    {
    typedef const Var_t Object_t::*MemberVarPtr_t;
    MemberVarPtr_t memberVarPtr;

    public:
    MemberVarComparator(MemberVarPtr_t ptr): memberVarPtr(ptr) {}

    bool operator()(const Object_t& obj1, const Object_t& obj2) const
    {
    return obj1.*memberVarPtr < obj2.*memberVarPtr;
    }
    };

    template<typename Object_t, typename Var_t>
    MemberVarComparator<Object_t, Var_t>
    makeMemberComparator(const Var_t Object_t::*memberVarPtr)
    {
    return MemberVarComparator<Object_t, Var_t>(memberVarPtr);
    }
    //--------------------------------------------------------------------

    Of course this will always sort using operator<. I'll leave it as an
    exercise to enhance the class and the makeMemberComparator() function to
    support specifying the comparison type (such as eg. std::greater), the
    default being, naturally, std::less.
     
    Juha Nieminen, Feb 23, 2010
    #1
    1. Advertising

  2. Juha Nieminen

    Noah Roberts Guest

    In article <4b840220$0$2025$>, lid
    says...
    >
    > Assume you have some kind of struct with several member variables. For
    > the same of simplicity, let's assume that your struct is like:
    >
    > struct Info
    > {
    > str::string name;
    > int age;
    > };
    >
    > Now, suppose you have, for example, a vector of objects of type Info,
    > and you would like to be able to sort the vector either by name or by age.
    > Bummer, you'll have to write two comparators for this. However, wouldn't
    > it be nice if you could just do something like this:
    >
    > // Sort the array by name:
    > std::sort(array.begin(), array.end(),
    > makeMemberComparator(&Info::name);
    >
    > or
    >
    > // Sort the array by age:
    > std::sort(array.begin(), array.end(),
    > makeMemberComparator(&Info::age);


    With boost or in the C++0x you can do this with bind:

    std::sort(cont.begin(), cont.end(), bind(&Info::name, _1) < bind
    (&Info::name, _2));

    or

    std::sort(cont.begin(), cont.end(), bind(&Info::age, _1) < bind
    (&Info::age, _2));

    This works with boost anyway. Not sure if the next standard will have
    the < operator for binders defined. If not, you could always bind
    std::less<> like so:

    bind(std::less<std::string>, bind(&Info::name,_1), bind(&Info::name, _
    2))

    I don't know how I'd live without bind. I used to have to where I work
    but I made a loud enough stink for long enough that we get to use it
    now. No more need to hand build custom things like what you just did
    for simple tasks.

    Great example if you're stuck without bind though.

    --
    http://crazyeddiecpp.blogspot.com
     
    Noah Roberts, Feb 23, 2010
    #2
    1. Advertising

  3. Juha Nieminen

    Brian Guest

    On Feb 23, 10:52 am, Noah Roberts <> wrote:

    >
    > Great example if you're stuck without bind though.
    >



    I dislike the _1, _2, etc. of bind, though. Juha's
    approach seems reasonable even if you could use bind.


    Brian Wood
    http://webEbenezer.net
    (651) 251-9384
     
    Brian, Feb 23, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Medi Montaseri
    Replies:
    17
    Views:
    876
    Medi Montaseri
    Sep 3, 2003
  2. slide_o_mix
    Replies:
    0
    Views:
    422
    slide_o_mix
    Oct 15, 2003
  3. Alex
    Replies:
    0
    Views:
    393
  4. C#
    Replies:
    4
    Views:
    411
  5. Peng Yu
    Replies:
    3
    Views:
    1,084
    Simon Forman
    Sep 21, 2009
Loading...

Share This Page