Search code examples
c++c++14shared-ptrstd-function

std::shared_ptr with std::function as custom deleter and allocator


Is there a way to make this work?

#include <functional>
#include <memory>
int main()
{
    std::function<unsigned char*(size_t)> allocator 
    = [](size_t size){
        return new unsigned char[size];
    };    
    std::function<void(unsigned char*)> deleter 
    = [](unsigned char* ptr){
        delete[] ptr;
    };
    std::shared_ptr<unsigned char[]> mem(size_t,deleter,allocator);
    return EXIT_SUCCESS;
}

I get the error:

main.cpp: In function ‘int main()’:
main.cpp:15:49: error: ‘deleter’ is not a type
     std::shared_ptr<unsigned char[]> mem(size_t,deleter,allocator);
                                                 ^~~~~~~
main.cpp:15:57: error: ‘allocator’ is not a type
     std::shared_ptr<unsigned char[]> mem(size_t,deleter,allocator);
                                                         ^~~~~~~~~

Some more context:

I have template class, which holds some memory. This is done with a shared_ptr, which is created with a custom Allocator and Deleter. The Allocator and Deleter are not template parameters of the class.

I now want to add a resize method to the class. I would like to avoid the need to provide a new Allocator and Delter and want to save them in std::function.


Solution

  • The allocator is not supposed to handle your data allocation, it should handle the allocation of shared_ptr's internal data.

    You need provide the already allocated data as first argument to the constructor. shared_ptr takes only care the of memory clean up.

    Furthermore the template argument of shared_ptr needs to be the type without indirection.

    #include <functional>
    #include <memory>
    int main()
    {
        std::function<void(unsigned char*)> deleter 
        = [](unsigned char* ptr){
            delete[] ptr;
        };
        std::shared_ptr<unsigned char> mem(new unsigned char[5], deleter);
        return EXIT_SUCCESS;
    }
    

    If you can you should prefer a lambda over std::function, it leaves the compiler possibilities to optimize.