2013-08-24 32 views
2

如何創建一個比較器來比較不同的字段。不同的字段可以有不同的類型(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; 
    } 
//.... 
} 
+3

此代碼是否可以編譯?通過價值傳遞,iRight/iLeft是引用,但指針應用? – billz

+0

...這個......比較器返回「更大」的狀態,而不是「更小」(是的,這*可能是有目的的,但有些東西告訴我...沒有。 – WhozCraig

+0

是的,我需要通過引用傳遞。在比較器中,我需要傳遞對象的指針,但問題不在於此。 – YYY

回答

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'; 
} 
+0

這正是我需要的。 – YYY

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