2010-04-12 20 views
62

Próbuję zmienić domyślną kolejność elementów w zbiorze liczb całkowitych być leksykograficzny zamiast numeryczna, i nie mogę uzyskać następujące skompilować z g ++:Korzystanie zwyczaj std :: set komparator

file.cpp:

bool lex_compare(const int64_t &a, const int64_t &b) 
{ 
    stringstream s1,s2; 
    s1 << a; 
    s2 << b; 
    return s1.str() < s2.str(); 
} 

void foo() 
{ 
    set<int64_t, lex_compare> s; 
    s.insert(1); 
    ... 
} 

pojawia się następujący błąd:

error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Compare, class _Alloc> class std::set’ 
error: expected a type, got ‘lex_compare’ 

co robię źle?

Odpowiedz

107

Używa się funkcji, w której powinno się używać funktora (klasy, która przeciąża operator(), aby można ją było nazwać funkcją).

struct lex_compare { 
    bool operator() (const int64_t& lhs, const int64_t& rhs) const { 
     stringstream s1, s2; 
     s1 << lhs; 
     s2 << rhs; 
     return s1.str() < s2.str(); 
    } 
}; 

następnie użyć nazwy klasy jako parametru type

set<int64_t, lex_compare> s; 

Jeśli chcesz uniknąć funktora kod szablonowe można również użyć wskaźnika funkcji (zakładając lex_compare jest funkcją).

set<int64_t, bool(*)(const int64_t& lhs, const int64_t& rhs)> s(&lex_compare); 
+0

faktycznie mój problem pojawił się dodatkowy zamykania> w zgłoszeniu zbioru. Zamykam pytanie jako fałszywe. (używając prostej funkcji zamiast funktora jest całkowicie w porządku dla STL) –

+0

kod w pytaniu jest prostszy niż proponowany (dla prostego komparatora funkcji) i działa dobrze. –

+4

@Omry: Byłbym zainteresowany wiedząc, jakiego kompilatora używasz: http://codepad.org/IprafuVf –

14

Odpowiedź Yacoby'ego inspiruje mnie do napisania adaptera do enkapsulacji funplateplate'a.

template< class T, bool (*comp)(T const &, T const &) > 
class set_funcomp { 
    struct ftor { 
     bool operator()(T const &l, T const &r) 
      { return comp(l, r); } 
    }; 
public: 
    typedef std::set< T, ftor > t; 
}; 

// usage 

bool my_comparison(foo const &l, foo const &r); 
set_funcomp< foo, my_comparison >::t boo; // just the way you want it! 

Wow, myślę, że było warto!

+9

Kwestia opinii, tak myślę. –

4

Można użyć komparatora funkcjonować bez owijania go tak:

bool comparator(const MyType &lhs, const MyType &rhs) 
{ 
    return [...]; 
} 

std::set<MyType, bool(*)(const MyType&, const MyType&)> mySet(&comparator); 

który jest irytujące, aby wpisać się za każdym razem trzeba zestaw tego typu i może powodować problemy, jeśli nie tworzyć wszystko zestawy z tym samym komparatorem.

7

C++ 11 Rozwiązanie z lambda i bez funkcji lub struct:

auto cmp = [](int a, int b) { return ... }; 
set<int, decltype(cmp)> s(cmp); 

Ideone

+0

typ zwrotu dla lambda? – user501138

+0

@ user501138, prawda, jeśli 'a diraria

Powiązane problemy