nedak96
nedak96

Reputation: 5

Function pointer with templated parameter

Right now I have a class template for a smart pointer that has a member function pointer because I need to call the destructor of the derived class, when the class is declared with the base function type. The function pointer is declared by:

void (*d)(const void*);

Defined by:

template<typename T> void DefaultDeleter(const void *p) { delete static_cast<T*>(const_cast<void*>(p)); }

Initialized with:

d = &DefaultDeleter<U>;

Called with:

d(static_cast<const void*>(px));

I want to change it so I don't have to keep casting the pointer because I think it might be messing something up. I want to change the definition to:

template<typename T> void DefaultDeleter(T *p) { delete p; }

Which would be declared by:

template<typename U> void (*d)(U*);

This doesn't work, though. Does anyone have any ideas on a way around this? Thanks so much in advance!

Tests with these classes work:

class Base1 {
    protected:
        Base1() : derived_destructor_called(false) {
            printf("Base1::Base1()\n");
        }
    private:
        Base1(const Base1 &); // Disallow.
        Base1 &operator=(const Base1 &); // Disallow.
    protected:
        ~Base1() {
            printf("Base1::~Base1()\n");
            assert(derived_destructor_called);
        }
    protected:
        bool derived_destructor_called;
};

class Derived : public Base1 {
        friend void basic_tests_1();
    private:
        Derived() {}
        Derived(const Derived &); // Disallow.
        Derived &operator=(const Derived &); // Disallow.
    public:
        ~Derived() {
            printf("Derived::~Derived()\n");
            derived_destructor_called = true;
        }
        int value;
};

But, I get memory errors about invalid pointers with the Derived_mi class and the only reason I could think of is something happens to it during casting:

class Base2 {
    protected:
        Base2() : derived_destructor_called(false) {
            printf("Base2::Base2()\n");
        }
    private:
        Base2(const Base2 &); // Disallow.
        Base2 &operator=(const Base2 &); // Disallow.
    protected:
        ~Base2() {
            printf("Base2::~Base2()\n");
            assert(derived_destructor_called);
        }
    protected:
        bool derived_destructor_called;
};

class Derived_mi : public Base1, public Base2 {
        friend void basic_tests_1();
    private:
        Derived_mi() {}
        Derived_mi(const Derived_mi &); // Disallow.
        Derived_mi &operator=(const Derived_mi &); // Disallow.
    public:
        ~Derived_mi() {
            printf("Derived_mi::~Derived_mi()\n");
            Base1::derived_destructor_called = true;
            Base2::derived_destructor_called = true;
        }
        int value;
};

Upvotes: 0

Views: 54

Answers (1)

Sneftel
Sneftel

Reputation: 41454

You can't have a templated function pointer, simply because different instantiations of the function template are different functions and can't all be pointed to by the same pointer.

It's instructive to look at std::shared_ptr, which coincidentally has a type-specific deleter callback. The way that works is that the deleter is created for a particular type, not for just any type. That is, a shared_ptr<Foo> has a deleter, but it's a deleter-of-Foos, and couldn't be used to delete Bars.

In addition to actually compiling, that has the advantage of allowing the creation of deleters which are meant to work with specific types. So in your situation, I'd suggest that you shouldn't try to change the type of d; instead you should change the structure that d is stored in, such that it can hold a type-specific deleter rather than a generic one.

Upvotes: 1

Related Questions