Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I store functors in non-template classes?

I've noticed that when I use std::shared_ptr (or any other smart pointer) a custom allocator/deleter is assigned through the ctor, which happens to be a template. My question is: how is the allocator/deleter stored and used?

Are these functors stored as a function pointer, void*, or what? Is it an indirect call, or a direct call?

Just to have more of a clear understanding of what I'm trying to ask, consider the following code:

struct SomethingAwesomeDeleter
{
public:
    void operator()(SomethingAwesome* ptr) const
    {
        // do something awesome
        delete ptr;
    }
};
typedef std::shared_ptr<SomethingAwesome> SomethingAwesomePtr;

SomethingAwesomePtr ptr{new SomethingAwesome, SomethingAwesomeDeleter{}};

How is SomethingAwesomeDeleter{} stored and used?

NOTE: I do realise std::shared_ptr is a template class, however std::shared_ptr does not have template arguments for the deleter/allocator in the class template arguments, i.e. there is no such template class as std::shared_ptr<T, Allocator, Deleter>.

like image 539
miguel.martin Avatar asked Nov 17 '25 14:11

miguel.martin


1 Answers

You can store any function object in a std::function. This takes care of either storing the function pointer directly (if it is a plain function) or wrapping it inside some object. That's one possible way to implement a shared_ptr deleter without having the function type being part of the template type.

Example (untested, just to give you the idea)

// This is the struct which actually holds the shared pointer
// A shared_ptr would reference count this
template <typename T>
class shared_ptr_shared
{
    std::function<void (T*)> del_;
    T* p_;
    // other members

    template <typename Deleter>
    shared_ptr_shared (T* obj, Deleter deleter)
    : p_ (p)
    , del_ (deleter)
    {
    }

    ~shared_ptr_shared ()
    {
        if (del_) {
            del_ (p_);
        } else {
            delete p_;
        }
    }
};

You can find out more about std::function does this here: how boost::function and boost::bind work

like image 139
Anteru Avatar answered Nov 19 '25 05:11

Anteru