Pointer to std::function<>

I have a problem where I want to copy a std::function<> object around. The implementation of the actual std::function class is rather complicated -- it involves templates and virtual functions.

Let me just get rid of this and copy a pointer to a heap generated pointer to the std::function object instead. This is fine but it doesn't work.
1
2
3
4
5
6
7
8
9
10
11
void some_call(void *arg)
{
    std::function<void()> **g = static_cast<std::function<void()> **>(arg);
    (**g)();
    delete *g;
} 

void g(int *, int);

std::function<void()> *f = new std::function<void()>([=] { g(ptr, val); });
some_call(&f);

Do I need to make special considerations for a std::function object when using it like this on the heap?
Last edited on
g is a pointer to a pointer.
*g is a pointer.
You need to dereference once more to get the std::function<void()> object on which you can invoke the call operator.
 
(**g)();
Last edited on
Pardon me that should be (**g)();
Syntax error.

However the original problem is still not solved. The program runs, the syntax is fine. But the output doesn't carry the information of the std::function properly. There is information missing from the original capture data fed into *f.

For example, say:

1
2
3
4
void g(int *p, int v)
{
  std::cout << *p << " " << v << std::endl;
}


I get a valid output for v corresponding to input variable 'var' But *p = 0 despite *ptr != 0;
This seems wrong:

 
std::function<void()> *f = new std::function<void()>([=] { g(ptr, val); });


Running through a mem debugger gives an invalid read of size 4 with the lambda. Do I need to make additional allocations?

1
2
3
4
5
Invalid read of size 4
==1115218==    at 0x109491: g(int, int*)
==1115218==    by 0x10954D: main::{lambda()#1}::operator()() const
==1115218==    by 0x109798: std::_Function_handler<void (), main::{lambda()#1}>::_M_invoke(std::_Any_data const&) (std_function.h:297)
==1115218==    by 0x109CA1: std::function<void ()>::operator()() const (std_function.h:687)
Scratch that. The pointer ptr was being deleted before the call to g. So my mistake.

I would have expected that std::function<()> copies the [] function as part of the object. It does indeed do that and works as expected.

Thank you.
std::function<void()> *f = new std::function<void()>
¿why? ¿why dynamic allocation?


>This is fine but it doesn't work.
then it is not fine
also, you should be more descriptive than «it doesn't work»


> Scratch that. The pointer ptr was being deleted before the call to g
¿more foot shooting?
one of the reason you should post enough code to reproduce your issue
Why dynamic allocation??

Why??

Why?

I can then carry an int32_t or int64_t pointer around. If you noticed I don't want to take care of a complicated object like std::function that could potentially involving copy/move semantics. I also use some C calls and these only care about the size of an object. So the only size I can care about is the size of a int_t pointer.
VMsrVT2Tyc wrote:
I can then carry an int32_t or int64_t pointer around
that's what std::function is, a (fat) pointer to a dynamically-allocated object. You're carrying a pointer to a dynamically-allocated pointer. It's just like doing vector<int>* p = new vector<int>;

copies the [] function as part of the object
yes, making a copy of std::function will deep-copy the object it points to, and if it's expensive for you, it may justify passing a reference (or, indeed, a pointer) to your std::function, but it does not justify the additional dynamic allocation.
Thanks for this. some good info to know.
I can't pass a reference to std::function as the program works async via threads. As soon as the std::function object is created it's passed (by copy) to another thread and the stack detaches. Hence the reason for a copy is essential, whatever its form.

Are you saying that it's reasonable to copy std::function instead of allocating on the heap? On my machine sizeof std::function<()> takes a fixed 32 bytes regardless of capture data. My program uses C calls elsewhere. These C calls copy and access structures of fixed size. Hence I need a C++ object that I can deal with for these calls though casting and it works.

I don't fully know the complete implementation of std::function except that it's a template of a functor using variadic arguments. Now if the object contains both data and pointers then it's safe to copy it around. Now given that std::function is of fixed size regardless of capture data suggests that std::function<> holds pointers to such data which are in turn dynamically allocated. If this is the case then it would seem safe to shallow copy the object within the scope of the program because the pointers to the data also just get copied and no data is lost or changed.

I asked a question along these lines on SO and I got totally daft responses from people who didn't even bother understanding the question. Basically their responses were that you can't copy std::function<>. They meant you can't shallow copy std::function<>. But I've been carrying out a few experiments of my own and it seem that I can just copy std::function. If this is the case then yes I'd agree that dynamical alloc in the same vain as vector<int>* p = new vector<int> is unnecessary and OTT.

The basic point is that I most definitely need to store my std::function objects somewhere. That means making a copy of it after creation.
Topic archived. No new replies allowed.