不同班级成员的比较者

时间:2013-08-24 09:40:28

标签: c++ oop compare

如何创建一个比较器以在不同的字段上进行比较。不同的字段可以有不同的类型(uintstring)。我应该使用T *吗?

有必要减少代码长度。

template<typename T>
class ComparatorSelector
{
public:
    struct CompareByLabel{
        bool operator() ( const T & iRight, const T & iLeft )
        {
            return iRight->m_label > iLeft->m_label;
        }
    };
    struct CompareByHouseNumber{
        bool operator() ( const T & iRight, const T & iLeft )
        {
            return iRight->m_houseNumber > iLeft->m_houseNumber;
        }
    };
    //...
};


template< class T, class C, typename W >
class SearchIndex
{
public:
    SearchIndex() {}

    void Build( std::vector< T > iElems, C iComparator, std::ofstream oStream )
    {
        std::map< T *, size_t> numbersOfElems;

        for( class std::vector<T>::iterator it = iElems.begin(); it != iElems.end(); ++it){
            m_elems.insert( &(*it));
            numbersOfElems[&(*it)] = m_elems.end - it ;
        }

        oStream << m_elems.size();
        for( class std::multiset< T * >::iterator it = m_elems.begin(); it!= m_elems.end(); ++it )
            oStream << numbersOfElems[*it];

        m_compareMode = iComparator;
    }
//....
}

2 个答案:

答案 0 :(得分:2)

您可以使用指向成员的指针来自定义比较器对象。更慢但更简单的方法是:

#include <iostream>

template <typename Type, typename Class>
class comparator
{
    Type Class::*d_member;
public:
    comparator(Type Class::*member): d_member(member) {}
    bool operator()(Class const& object0, Class const& object1) const {
        return object0.*(this->d_member) < object1.*(this->d_member);
    }
};

template <typename Type, typename Class>
comparator<Type, Class>
make_comparator(Type Class::*member)
{
    return comparator<Type, Class>(member);
}

int main()
{
    typedef std::pair<int, double> pair;
    pair p0(17, 3.14);
    pair p1(42, 2.7);
    std::cout << std::boolalpha
              << "first: " << make_comparator(&pair::first)(p0, p1) << ' '
              << "second: " << make_comparator(&pair::second)(p0, p1) << ' '
              << '\n';
}

由于此版本在运行时使用指向成员的指针,因此无法轻松内联,因此不会像您希望的那样快。该成员也可以嵌入到比较器的类型中,这使得它的使用有点烦人:

template <typename Type, typename Class, Type Class::*Member>
class comparator
{
public:
    bool operator()(Class const& object0, Class const& object1) const {
        return object0.*Member < object1.*Member;
    }
};

int main()
{
    typedef std::pair<int, double> pair;
    pair p0(17, 3.14);
    pair p1(42, 2.7);
    std::cout << std::boolalpha
              << "first: " << comparator<int, pair, &pair::first>()(p0, p1) << ' '
              << "second: " << comparator<double, pair, &pair::second>()(p0, p1) << ' '
              << '\n';
}

答案 1 :(得分:0)

这是使用不同类型的不同字段的比较器示例:

#include <set>

using namespace std;

class House {
public:
    string m_label;
    int m_houseNumber;
};

class HouseCompare {
public:
    bool operator()( const House& a, const House& b)
    {
        if (a.m_houseNumber>0 && b.m_houseNumber>0)
            return a.m_houseNumber < b.m_houseNumber;
        else if (a.m_houseNumber>0)
            return false;
        else if (b.m_houseNumber)
            return true;
        else
            return a.m_label < b.m_label;
    }
};

int main(int argc, char *argv[])
{
    typedef multiset<House, HouseCompare> Houses;

    Houses houses;
    House house_data[] = {
        {"foo", 1},
        {"foo1", 0},
        {"foo0", 0},
        {"foo", 2}
    };
    houses.insert (house_data, house_data+sizeof(house_data)/sizeof(House));

    for (Houses::iterator i = houses.begin (); i != houses.end (); ++i)
        cout << i->m_houseNumber << ": " << i->m_label << endl;

    return 0;
}

输出:

0: foo0
0: foo1
1: foo
2: foo