четверг, 2 июня 2011 г.

OMG, pointer to member

struct foo
{
public:
    int d;
    std::string s;
};

struct comparator;
struct comparator_proxy
{
    comparator const *ptr;
public:
    comparator_proxy(comparator const *ptr) : ptr(ptr) {}
    bool operator()(foo const &a, foo const &b) const;
};

struct comparator
{
    virtual ~comparator() {}
    virtual bool operator()(foo const &, foo const &) const = 0;
    comparator_proxy proxy() const
    {
        return comparator_proxy(this);
    }
};

bool comparator_proxy::operator()(foo const &a, foo const &b) const
{
    return (*ptr)(a, b);
}


template<typename T>
struct member_comparator : comparator
{
    T foo::*data;

    explicit member_comparator(T foo::*data) : data(data) {}
    
    bool operator()(foo const &a, foo const &b) const 
    {
        return a.*data < b.*data;      
    }
};


template<typename T>
std::auto_ptr<comparator> make_member_comparator(T foo::*ptr)
{
    return std::auto_ptr<comparator>(new member_comparator<t>(ptr));
}

struct boo
{
    std::vector<foo> arr;

    void sort_by(int num)
    {
        static std::auto_ptr<comparator> member[] = {
            make_member_comparator(&foo::d),
            make_member_comparator(&foo::s),
        };
        std::sort(arr.begin(), arr.end(), member[num]->proxy());
    }
};
@from

Комментариев нет: