Как определить шаблон для указателей и динамического выделения памяти?

Я сделал шаблон класса под названием Очередь но у меня возникают проблемы при попытке создать экземпляр с указателем на другой класс с именем Worker в качестве типа. Queue<Worker*>

Я думаю, что проблема заключается в следующем методе:

// Add item to queue
template <typename Type>
bool Queue<Type>::enqueue(const Type& item)
{
if (isfull())
return false;
Node* add = new Node; // create node
// on failure, new throws std::bad_alloc exception
add->item = item; // set node pointers (shallow copying!!!!!)
add->next = nullptr;
items++;
if (front == nullptr) // if queue is empty,
front = add; // place item at front
else
rear->next = add; // else place at rear
rear = add; // have rear point to new node
return true;
}

В случае, когда параметр типа является указателем, мне нужно скопировать указанное значение, а не адрес (я использую динамическое управление памятью), чтобы избежать сбоя программы.

Я не знаю, как решить это с помощью шаблона.

Любая помощь?

1

Решение

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

Так, например:

template<typename T>
base_queue; //keep everything "common" in this class

template<typename T>
queue : public base_queue<T> { ... }; //unspecialized queue class

template<typename T>
queue<T*> : public base_queue<T> { ... }; //pointer specialized version

Теперь в специализированной версии вашего Queue<T*> класс, твой enqueue Метод может выглядеть следующим образом:

template <typename T>
bool Queue<T*>::enqueue(const T* item)
{
//... code

add->item = *item; // copy the value being pointed to, not the pointer itself

//... more code

return true;
}
1

Другие решения

Используйте черты техники.

Я имею в виду определение простой структуры, в которой будет реализована вся магия. Примерно так: deep_copy:

  template <typename T>
struct deep_copy {
void do_copy(T& d, const T& s)
{
d = s;
}
};

И специализация для указателей

   template <typename T>
struct deep_copy<T*> {
void do_copy(T*& d, const T* s)
{
if(s) d=new(*s); else d=0; }};
}
};

[UPDATE1] Подробнее и больше примеров:

И используйте deep_copy в своей очереди:

template <typename T>
class Queue {
public:
void push_back(const T& elem)
{
Node* n = new Node();
copyTraits.doCopy(n->elem, elem);
}
private:
deep_copy<T> copyTraits;
};

Или даже лучше сделать его параметром по умолчанию для вашего шаблона, как меньше<> по умолчанию для карты.

template <typename T, typename CopyTraits = deep_copy<T> >
class Queue {
public:
void push_back(const T& elem)
{
Node* n = new Node();
copyTraits.doCopy(n->elem, elem);
}
private:
CopyTraits copyTraits;
};

И не забудьте про метод уничтожения, если хотите Queue::~Qeueu() д-тор на всякий случай:

  template <typename T>
struct deep_copy {
void do_copy(T& d, const T& s)
{
d = s;
}
void do_destroy(const T& elem) {} // do nothing
};template <typename T>
struct deep_copy<T*> {
void do_copy(T*& d, const T* s)
{
if(s) d=new(*s); else d=0; }};
}
void do_destroy(const T& elem) {
delete elem;
}
};template <typename T, typename AllocTraits = deep_copy<T> >
class Queue {
public:
...
~Queue() {
for (n in Nodes) { // pseudo-code
allocTraits.doDestroy(n->elem);
}
}
private:
AllocTraits allocTraits;
};
2