Home > Back-end >  Determine how external memory is allocated when using a std::function object
Determine how external memory is allocated when using a std::function object

Time:04-06

Is there a way to determine how the external memory of a std::function object is allocated? std::function might not allocate external memory if it is feed with a raw C function pointer, but it might get a std::bind() object, and it is not prepared to store copied std::function objects of any size, so it has to allocate external memory in this case.

CodePudding user response:

Is there a way to determine how the external memory of a std::function object is allocated?

No, there isn't – at least not any more (since C 17), see comments to question.

I need function<>-objects because they can store a whole callable object with its contents, in case of a bind()-object the parameters for it.

Well, you can always re-write standard templates and modify their behaviour in a manner that suits your own needs. What about a template class that copies the target (e.g. the bind object) and provides an operator() that itself calls the bind object? You can provide your own memory management there then:

class Function
{
    class WrapperBase
    {
        virtual ~WrapperBase() { }
        virtual void operator()() = 0; // with appropriate return type
                                       // and parameters – you could make
                                       // Function a template for
    };

    template <typename T>
    class Wrapper
    {
        T m_t;
    public:
        Wrapper(T& t) : m_t(t) { }
        void operator()() override
        {
            m_t();
        }
    };

public:
    template <typename T>
    Function(T& t)
    {
        void* memory = nullptr; // your personal memory allocation instead
                                // consider correct size and alignment!
        m_t = new (memory) Wrapper<T>(t);
    }
    ~Function()
    {
        m_t->~Wrapper(); // destructor needs to be called explicitly
        // free the memory of m_t according to your personal allocation strategy
    }
    
    void operator()()
    {
        (*m_t)();
    }

private:
    WrapperBase* m_wrapper;
};

The example is incomplete, not considering const-ness of T, move construction etc. – you might want to add on your own.

You might want to avoid copying entirely and just store references – or specialise the templates such that objects received by normal references are stored as references only while objects received by rvalue references are copied. Endless possibilities...

CodePudding user response:

Allocator support for std::function was deprecated for C 17 and not well supported by the libraries before C 17.

cppreference for example says:

std::function's allocator support was poorly specified and inconsistently implemented. Some implementations do not provide overloads (6-10) [these are the constructors with allocator support] at all, some provide the overloads but ignore the supplied allocator argument, and some provide the overloads and use the supplied allocator for construction but not when the std::function is reassigned. As a result, allocator support was removed in C 17.

The corresponding proposal with a more detailed explanation has been given in the comments to your question by @unddoch.

So I am afraid, that the answer to your question is no. There is no allocator support in std::function.

  • Related