Пользовательский класс как параметр шаблона

Я повторно реализую std::map. Мне нужно убедиться, что ключ любого типа данных (базовый или определяемый пользователем) будет работать с ним. Я объявил класс Map как шаблон, который имеет два параметра для ключа и значения. Мой вопрос: если мне нужно использовать строку в качестве типа ключа, как я могу перегрузить операторы ‹ и > только для ключей строкового типа?? В специализации шаблона мы должны специализировать весь класс с помощью тип, который нам нужен, насколько я понимаю.
Можно ли как-то сделать это лучше?? Что, если я добавлю отдельный класс Key и использую его в качестве типа шаблона для Key?


person Izza    schedule 20.05.2010    source источник


Ответы (2)


Вы должны выделить сравнение как тип, как это делает обычный std::map. То есть иметь служебный класс less_compare:

template <typename T>
struct less_compare
{
    bool operator()(const T& pLhs, const T& pRhs) const
    {
        return pLhs < pRhs;
    }
};

А потом:

template <typename Key, typename Value, typename Compare = less_compare<Key> >
class map
{
    // ...

private:
    Compare mCompare;
};

И чтобы сравнить два значения, выполните: if (mCompare(someThing, someOtherThing)), что будет верно, если someThing будет "меньше" someOtherThing. Обратите внимание, что этот факторинг также допускает определяемые пользователем сравнения (именно поэтому в кавычках указано «меньше»). Это известно как дизайн, основанный на политике.

И теперь вы можете специализировать только класс less_compare для C-струн. (А также предоставить greater_compare и род.)


Имейте в виду, если это не для обучения, вы не должны реализовывать свою собственную карту. Также обратите внимание, что std::string уже перегружен operator<.

person GManNickG    schedule 20.05.2010
comment
Большое спасибо за немедленный ответ, и да, это для учебных целей. Я новичок в шаблонах, поэтому хотел немного запачкать руки :D - person Izza; 20.05.2010
comment
Просто из любопытства, но почему бы нам не реализовать свои собственные карты?? - person Izza; 20.05.2010
comment
@isurulucky: Поскольку вы делаете это для практики, все в порядке. Но вообще не стоит тратить время на то, что уже сделано. (Если вам нужна карта, включите <map> и используйте std::map.) Тем более, что то, что уже сделано, было (и есть) сильно оптимизировано и протестировано. - person GManNickG; 20.05.2010
comment
Привет, я сделал то, что ты сказал. До сих пор это работало хорошо. Но когда я изменяю код перегрузки () для работы с определенным пользователем объектом (скажем, структурой с целым числом в ней), я снова получаю некоторые ошибки ссылки, говоря, что оператор () уже определен. В чем тут дело?? PS: Я также использовал охранники. - person Izza; 31.05.2010
comment
@isurulucky: я бы начал с этого новый вопрос. Убедитесь, что вы включили весь соответствующий код. - person GManNickG; 31.05.2010
comment
@GMan: Хорошо, сделал это только что :) - person Izza; 31.05.2010

Вы также можете использовать типовые черты. Это даст вам основу для решения возможных будущих различий между типами.

person FireAphis    schedule 20.05.2010