Как избежать лишнего копирования кода?

Рейтинг: 1Ответов: 1Опубликовано: 09.07.2023

Я пытаюсь реализовать класс бинарной кучи с ее основными методами, но есть нюанс: с помощью шаблона хочу сделать 2 класса. Если подан false, будет куча, построенная вокруг максимума, если true - куча, построенная вокруг минимума (да, я хочу реализовать это именно с помощью шаблонов, в качестве учебного задания). Я хочу как можно больше избежать повторения кода при написании специализации false.

#include<iostream>
#pragma once

template<bool T>
class binaryHeap{
public:
    binaryHeap();
    ~binaryHeap();

    void insert(int);
    int getMin();
    void extractMin();
    bool isEmpty();

private:
    static const int none_val = -123;

    void siftUp(int);
    void siftDown(int);
    int* a;
    int size_;
};

Я пытаюсь провернуть это так (да, пока что это пустой класс):

template<>
class binaryHeap<false>: public binaryHeap<true>{

};

Собственно, вопрос: как унаследоваться так, чтобы методы binaryHeap<true>::binaryHeap() и binaryHeap<true>::~binaryHeap() совпадали с теми же в binaryHeap<false>, не пиша идентичного кода, или это невозможно реализовать?

P.S Методы для полной специализации true уже реализованы в отдельном .cpp файле, включая binaryHeap() и ~binaryHeap()

P.P.S может, как-то прикрутить виртуальные конструктор и деструктор?

Ответы

▲ 3

Лучше всего скопировать с std::map, и передавать шаблонным параметром компаратор:

template <typename C = std::less<>>
class BinaryHeap {...};

Тогда для BinaryHeap<> (он же BinaryHeap<std::less<>>) C{}(x, y) будет делать x < y.

А для обратного порядка вы бы писали BinaryHeap<std::greater<>>, и в нем C{}(x, y) уже делал бы x > y.


Или, если хотите оставить bool, то, как правильно советуют, используйте if constexpr, чтобы не городить специализации.


template<>
class binaryHeap<false>: public binaryHeap<true>

Это не будет работать без виртуальных функций, а они добавляют оверхед по памяти и по скорости.

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

Обычно в таких ситуациях советуют заменить виртуальность на CRTP, чтобы не иметь оверхед. Но здесь от него толку немного, это будет сложнее чем просто буловый шаблонный параметр.


binaryHeap();
~binaryHeap();

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

int getMin();
bool isEmpty();

Забыт const на геттерах.


Еще, тут напрашивается тип элемента сделать шаблонным аругментом, а не хардкодить int.