key_type ассоциативных контейнеров
От: sokel Россия  
Дата: 05.04.10 07:07
Оценка:
Какие могли бы быть подводные камни если бы методы с использованием key_type были объявлены примерно так? :
template<typename key_type_comparable> iterator find(const key_type_comparable& k) const

Ну или на крайний случай могли бы сделать для этого отдельный метод, например t_find.
Тогда можно было бы избавиться от конструирования временных объектов в случае если тип, используемый при поиске не совпадает с реальным типом ключа:
#include <string>
#include <set>

using namespace std;

struct string_less
{
    bool operator ()(const char* s1, const string& s2) const { return s2.compare(s1) > 0; }
    bool operator ()(const string& s1, const char* s2) const { return s1 < s2; }
    bool operator ()(const string& s1, const string& s2) const { return s1 < s2; }
};

int main(void)
{
    typedef set<string, string_less> set_type;

    set_type s;

    s.insert("xxx");
    s.insert("yyy");
    s.insert("zzz");

    // при поиске не создается временная переменная типа string, 
    // поскольку компаратор не требует идентичности типов
    set_type::iterator it = s/*<const char*>*/.t_find("xxx");

    return 0;
}
Re: key_type ассоциативных контейнеров
От: sokel Россия  
Дата: 05.04.10 07:22
Оценка:
Или вот ещё вариант, std::set с упорядовачиванием по члену структуры и поиском по типу этого члена:
struct foo
{
    foo(int x, int y, int z) : x(x), y(y), z(z) {}
    int x,y,z;
};

template<class T,typename M, M T::*m_ptr>
struct member_less
{
    template<typename U> bool operator ()(const U& k, const T& v) const { return k < v.*m_ptr; }
    template<typename U> bool operator ()(const T& v, const U& k) const { return v.*m_ptr < k; }
    bool operator ()(const T& v1, const T& v2) const { return v1.*m_ptr < v2.*m_ptr; }
};

int main(void)
{
    // set<foo>, упорядоченный по x
    typedef set<foo, member_less<foo, int, &foo::x> > set_type;

    set_type s;

    s.insert(foo(1,2,3));
    s.insert(foo(2,3,4));
    s.insert(foo(4,5,6));

    // при поиске не требуется создавать переменную типа foo
    set_type::iterator it = s.find(2);

    return 0;
}
Re: key_type ассоциативных контейнеров
От: uzhas Ниоткуда  
Дата: 05.04.10 07:51
Оценка:
Здравствуйте, sokel, Вы писали:

S>Какие могли бы быть подводные камни если бы методы с использованием key_type были объявлены примерно так? :

S>
S>template<typename key_type_comparable> iterator find(const key_type_comparable& k) const

S>struct string_less
S>{
S>    bool operator ()(const char* s1, const string& s2) const { return s2.compare(s1) > 0; }
S>    bool operator ()(const string& s1, const char* s2) const { return s1 < s2; }
S>    bool operator ()(const string& s1, const string& s2) const { return s1 < s2; }
S>};
S>


Я думаю, что основная проблема в формализации, документировании и без того сложной библиотеки без особых выигрышей.
Надо описать, что же такое string_less — это уже не binary predicate, а чудо-юдо. Что такое сравнение двух _разных_ объектов? Каким свойством должен удовлетворять этот объект? Сейчас такие предикаты описываются как "The key comparison function, a Strict Weak Ordering ", с этим понятием знакомы студенты технических факультетов (из математики).
std::binary_search вполне подходит для твоей оптимизации поиска элемента, хотя я не уверен, что будет выигрыш, потому что std::set::begin() возвращает не RandomAccess Iterator, а лишь Forward Iterator
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.