Patrik Valkovič
Patrik Valkovič

Reputation: 724

Partial specialization for destructor

I am just working on my school homework, and I am interested if C++ could create specialized destructor for pointers. I know that this is not good practice, but because of performance, I want to do it this way. Also because I am curious about it. So lets say, that we have this class:

template<typename T,int(*comp)(const T& first, const T& second)>
class BinomialHeapLite
{
private:
    class Node
    {
        Node* next;
        T instance;
    }
    Node* top;
public:
    ~BinomialHeapLite();
}

Now I want destructor, that delete just node, if is T only type and delete also inner instance, if is T pointer..

template<typename T, int(*comp)(const T& first, const T& second)>
BinomialHeapLite<T,comp>::~BinomialHeapLite()
{
    //some code
    delete this->top;
}

template<typename T, int(*comp)(const T* &first, const T* &second)>
BinomialHeapLite<T*,comp>::~BinomialHeapLite()
{
    //some code
    delete this->top->instance;
    delete this->top;
}

But this give me "invalid use of incomplete type". I also want to use pure C++11, because I want to be independent to another libraries (also standards libraries), moreover that libraries are not permitted in out system. Is something like this possible in pure C++?

Upvotes: 0

Views: 1317

Answers (2)

felix
felix

Reputation: 2222

You can not partially specialize a member function. But you can partially specialize a class template:

template <class T>
struct Deallocator{
  template <class Node>
  static void Deallocate(const Node &node){}
};

template <class T>
struct Deallocator<T *>{
  template <class Node>
  static void Deallocate(const Node &node){}
};

template<typename T, int(*comp)(const T& first, const T& second)>
BinomialHeapLite<T,comp>::~BinomialHeapLite()
{
    //some code
    Deallocator<T>::Deallocate(top);
}

Or overload a function :

template<typename T,int(*comp)(const T& first, const T& second)>
class BinomialHeapLite
{
private:
    struct Node // a little change here
    {
        Node* next;
        T instance;
    };
    Node* top;

    template <class Ty>
    void deallocate(Ty *) {}
    template <class Ty>
    void deallocate(Ty &) {}
public:
    ~BinomialHeapLite();
};

template<typename T, int(*comp)(const T& first, const T& second)>
BinomialHeapLite<T,comp>::~BinomialHeapLite()
{
    //some code
    deallocate(top->instance);
}

Upvotes: 1

Vittorio Romeo
Vittorio Romeo

Reputation: 93274

You're giving your BinomialHeapLite class a responsibility that it shouldn't have: cleaning up instance if it's a heap-allocated pointer.

That burden should be on the user of your class: what if he is already calling delete in its own code? What if the object is supposed to be reused after your BinomialHeapLite is destroyed?

All your class should do is provide a generic container that manages its own memory. For that task, your should also use smart pointers (std::unique_ptr in this case):

template<typename T,int(*comp)(const T& first, const T& second)>
class BinomialHeapLite
{
private:
    class Node
    {
        std::unique_ptr<Node> next;
        T instance;
    }
    std::unique_ptr<Node> top;
}

You won't need an hand-written destructor then. Refer to the "rule of three/five/zero" for more information.


If you really want to implement your flawed/unconventional design, you could use a partially specialized helper struct that calls delete if its type is a pointer:

template <typename T>
struct dtor_helper
{
    static void do_it(T&&){}
};

template <typename T>
struct dtor_helper<T*>
{
    static void do_it(T* x){ delete x; }
};

template<typename T, int(*comp)(const T& first, const T& second)>
BinomialHeapLite<T,comp>::~BinomialHeapLite()
{
    //some code
    dtor_helper<T>::do_it(this->top->instance);
    delete this->top;
}

wandbox example

Upvotes: 1

Related Questions