Функция, которая полиморфно обрабатывает vector и hash_set - PullRequest
2 голосов
/ 07 сентября 2011

У меня есть функция в C ++, которая берет вектор и помещает в него некоторые элементы. Например:

void MyFunction(vector<int>* output);

Я хочу изменить его, чтобы теперь он мог принимать вектор или hash_set. В Java это было бы легко, просто измените функцию, чтобы получить коллекцию (общий интерфейс). Все, что делает MyFunction, это помещает элементы в заданный им контейнер, поэтому ему не нужно заботиться о том, является ли этот контейнер вектором или hash_set, только о том, что существует некоторое понятие «вставки» элемента.

Спасибо за вашу помощь!

Ответы [ 4 ]

3 голосов
/ 07 сентября 2011

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

Используйте шаблон, но используйте функцию вставки и вставьте элемент .end (), чтобы вектор поддерживал быстрые операции - ваша лучшая ставка.Вы все еще немного замедляете свой хэш-набор, хотя, если он принимает позицию вставки в качестве подсказки местоположения (хотя это будет работать).

Используя insert (iter, val), contianer расширяетсявставляя новые элементы перед элементом в позиции итератора.Это верно для контейнеров последовательности (вектор), в то время как ассоциативные контейнеры (hash_set) будут просто использовать позицию в качестве подсказки - но вставка все равно будет работать нормально.Приведенную ниже функцию можно использовать для вставки значения U в любой контейнер, поддерживающий вставку (все это делают в STL), если предположить, что U совпадает или неявно преобразуется в тип векторного элемента.

template <typename T, typename U>
void InsertToContainer(T& container, U val)
{
    container.insert(container.end(), val);
}
1 голос
/ 07 сентября 2011

Если я правильно понимаю, Вы можете использовать Повышение :: Вариант

0 голосов
/ 07 сентября 2011

Если вам нужно использовать методы, которые не являются общими для двух контейнеров, вы можете создать два производных класса-оболочки с чисто виртуальным базовым классом, который определяет общий интерфейс для операций, которые вы хотели бы выполнять с unordered_set и vector, которые не имеют одинаковых имен методов, а затем передают указатели или ссылки на базовый класс функции.

Например, ваш чисто виртуальный базовый класс может определять методы для вставки, поиска, итерации и т. Д. И может маскировать различия в именах методов и использовании методов между этими двумя контейнерами, которые выполняют операции этих типов. Ваши производные типы будут реальной реализацией чисто виртуальных методов в базовом классе. Ваша функция получит ссылку или указатель на базовый тип, и, поскольку базовый класс полиморфен, вы можете просто вызвать методы интерфейса, определенные базовым классом, и использовать как vector, так и unordered_set с вашей функцией. не беспокоясь о различиях в реализации и несоответствиях интерфейса между линейными контейнерами и ассоциативными контейнерами.

0 голосов
/ 07 сентября 2011

Шаблон функции позволит вам сделать его более общим:

 template<typename T, typename Cont = std::vector<T> > void MyFunction(T t, Cont c);

Здесь контейнером по умолчанию будет std::vector<T>, но вы все равно можете изменить контейнер, если хотите.

...