Шаблоны, универсальный контейнер и уникальный, C ++ - PullRequest
1 голос
/ 06 февраля 2011

Я создал универсальный контейнер, расширяющий возможности вектора ... Добавлена ​​новая функциональность для общих функций.

Однако у меня есть одна проблема: удаление дублирующихся уникальных элементов.Он состоит из нескольких этапов: сортировка, создание элементов уникальными, стирание ... Новая функциональность заключается в перенумерации объектов по первичному идентификатору и повторном вычислении некоторых хэшей.Так что это нельзя сделать вне класса List ...

Представим себе следующий пример универсального контейнера (упрощенно):

template <typename Item>
class List
{
protected:
            typename TList <Item>::Type items;
    ...
};

Сравнения были реализованы с использованием функторов ...

template <typename Item>
class isEqual
{
        public:
            bool operator() ( const Item &i1, const Item &i2 )   const
            {
                  ...
            }
};

Мы создаем новый список и удаляем дублирующиеся элементы:

List <Object> list;
list.rem_duplic(items.begin(), items.end(), isEqual <Object>);

Как реализовать функцию rem_duplicit, имеющую параметр шаблона ... Если List представляет класс шаблона, то параметр шаблонафунктор должен быть указан при объявлении списка:

List <Object, Comparator <Type> > list;

И это может быть ограничительным: дубликаты могут быть удалены только по одному критерию, функтор не может быть установлен при удалении дублирующих элементов ... Эта конструкция недопустима:

template <typename Item>
class List
{
protected:
            typename TList <Item>::Type items;
    public:
            template <typename Functor>
            void rem_duplic(typename TList <Item>::Type ::iterator begin, typename TList <Item>::Type ::iterator end, Functor <Item>) ();
            ...
};

template <typename Item> template <typename Functor>  //Illegal
void List<Item>::rem_duplic(typename TList <Item>::Type ::iterator begin,     typename TList   <Item>::Type ::iterator end, Functor <Item>)
{

}

Как я могу разумно реализовать такую ​​функцию, то есть что я могу сделать с шаблонным параметром

Functor <Item> ? 

Внутренняя функциональность между {} мне понятна ...

Ответы [ 2 ]

1 голос
/ 06 февраля 2011

Если вы хотите написать функцию, которая может принимать произвольную функцию сравнения / функтор в качестве параметра, сделайте эту функцию параметризованной по типу компаратора. Например:

template <typename ForwardIterator, typename Comparator>
void MakeUnique(ForwardIterator begin, ForwardIterator end,
                Comparator comp) {
    std::unique(begin, end, comp); // For example
}

Поскольку последний аргумент является параметром шаблона, вызывающие абоненты могут передавать данные любого типа, если они могут использоваться в качестве компаратора.

0 голосов
/ 06 февраля 2011

<Item> в последнем объявлении аргумента является излишним. Просто:

template <typename Functor>
void rem_duplic(items::iterator begin, items::iterator end, Functor f);

(обратите внимание, что вы можете использовать typedef, который вы ввели выше в объявлении, чтобы сократить его). Функция не заботится о том, является ли переданный аргумент шаблоном или нет - все, что ему нужно сделать, это вызвать его с аргументами (типа Item), и компилятор правильно подставит.

Фактически, иногда функтор будет шаблоном, а другие - просто функцией сравнения указанного типа.

Две ноты:

  1. Лучше сделать аргументы шаблона итераторами тоже. Зачем ограничивать себя предметами, поступающими из вашего контейнера. Помните, что простые указатели тоже являются итераторами, и, возможно, однажды у вас будет статический массив, или вы получите данные из другой библиотеки или чего-то еще.
  2. Семантика функции не совсем очевидна. Он принимает диапазон и что-то с ним делает, но в то же время это функция member , поэтому я предполагаю, что он что-то делает с инвокантом.

Обратите внимание, что в качестве аргумента можно объявить шаблон с другим шаблоном, но здесь ничего подобного не требуется.

...