test std::function validity after bind to member function - c++

For the struct:
struct A {
int var = 10;
void check() {
std::cout << "var is " << var << std::endl;
}
};
Say I create a std::function object of A::check(), using a dynamically allocated a object:
auto a_ptr = std::make_unique<A>();
std::function<void()> f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
f();
It would be nice for safety if I could test f to see if the bound A object is still alive. Is it possible to retrieve that information from f directly? Assume a_ptr is not accessible from the call point, so I can't test against a_ptr directly. Using std::function's operator bool, or testing f against nullptr don't work.

So you basically want your function object to test for the existence of the A instance managed by a_ptr, i see 3 ways of doing this with the current c++ std features.
-- Lambda with a reference to the unique_ptr
auto a_ptr = std::make_unique<A>();
std::function<void()> f = [&] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
This requires that the pointer is still alive anytime the function object is alive.
-- Lambda with a copy of the shared_ptr
auto a_ptr = std::make_shared<A>();
std::function<void()> f = [=] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
Same thing but without requirements on the lifetime relationship at the expense of some additional performance cost which is mainly the copy of a shared pointer, probably totally worth the headache it saves in most cases (i'm going to be burned by the optimisation guys for this one).
-- Custom deleter in your smart pointer that resets your function
std::function<void()> f;
auto a_ptr = std::unique_ptr<A, std::function<void(A*)>>(new A, [&](A*){ f = nullptr;});
f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
a_ptr.reset();
if (f)
f();
This requires that somehow your deleter can access the function to reset it, whether it is directly or through a storage system in your classes (containers of functions are a nice design imo).
You can also create more elaborated systems with your own primitives but that would lead you further away from the standard library. Ultimately you'll have to choose what's best in your situation mainly based on the lifespan and ownership relationships of your objects.

Well, this one is easy, use std::shared_ptr.
when you think about it , you basically want to ensure that some entity in you program is valid as long as something is using it.
In other words, you are looking for a shared_ptr.
Otherwise, the design looks a bit weird, if some single entity in your program is owning a_ptr, it should be the single owner of all the std::functions which uses this resource, which is not your intention. if that owner is not the owner of the std::function you are highly increasing the probability of segmentation faults, heap corruption and other stuff you don't want.

Related

Is it possible / desirable to create non-copyable shared pointer analogue (to enable weak_ptr tracking / borrow-type semantics)?

Problem: Unique_ptrs express ownership well, but cannot have their object lifetimes tracked by weak_ptrs. Shared_ptrs can be tracked by weak_ptrs but do not express ownership clearly.
Proposed solution: Derive a new pointer type (I'm going to call it strong_ptr) that is simply a shared_ptr but with the copy constructor and assignment operator deleted, so that it is hard to clone them. We then create another new borrowed_ptr type (which is not easily storable) to handle the temporary lifetime extension required when the weak_ptr accesses the object, and can thereby avoid using shared_ptrs explicitly anywhere.
This question Non-ownership copies of std::unique_ptr adn this one Better shared_ptr by distinct types for "ownership" and "reference"? are both similar but in both cases the choice is framed as simply unique_ptr vs shared_ptr and the answer does not propose a satisfactory solution to my mind. (Perhaps I should be answering those questions instead of asking a new one? Not sure what the correct etiquette is in this case.)
Here's a basic stab. Note that in order to avoid the user of the weak pointer having to convert to shared_ptr to use it, I create a borrowed_ptr type (thanks rust for the name) which wraps shared_ptr but makes it hard for the user to accidentally store it. So by using differently hamstrung shared_ptr derivatives we can express the intended ownership and guide the client code into correct usage.
#include <memory>
template <typename T>
// This owns the memory
class strong_ptr : public std::shared_ptr<T> {
public:
strong_ptr() = default;
strong_ptr(T* t) : std::shared_ptr<T>(t) {}
strong_ptr(const strong_ptr&) = delete;
strong_ptr& operator=(const strong_ptr&) = delete;
};
template <typename T>
// This can temporarily extend the lifetime but is intentionally hard to store
class borrowed_ptr : public std::shared_ptr<T> {
public:
borrowed_ptr() = delete;
borrowed_ptr(const borrowed_ptr&) = delete;
borrowed_ptr& operator=(const borrowed_ptr&) = delete;
template <typename T>
static borrowed_ptr borrow(const std::weak_ptr<T>& wp)
{
return wp.lock();
}
private:
borrowed_ptr(std::shared_ptr<T> &sp) : std::shared_ptr<T>(sp) {}
};
This seems fairly simple and an improvement over shared_ptr, but I cannot find any discussion of such a technique, so I can only imagine that I have missed an obvious flaw.
Can anyone give me a concrete reason why this is a bad idea? (And yes I know this is less efficient than unique_ptr - for PIMPL and so on I would still use unique_ptr.)
Caveat: I haven't yet used this in any more than a basic example, but this compiles and runs ok:
struct xxx
{
int yyy;
double zzz;
};
struct aaa
{
borrowed_ptr<xxx> naughty;
};
void testfun()
{
strong_ptr<xxx> stp = new xxx;
stp->yyy = 123;
stp->zzz = 0.456;
std::weak_ptr<xxx> wkp = stp;
// borrowed_ptr<xxx> shp = wkp.lock(); <-- Fails to compile as planned
// aaa badStruct { borrowed_ptr<xxx>::borrow(wkp) }; <-- Fails to compile as planned
// aaa anotherBadStruct; <-- Fails to compile as planned
borrowed_ptr<xxx> brp = borrowed_ptr<xxx>::borrow(wkp); // Only way to create the borrowed pointer
// std::cout << "wkp: " << wkp->yyy << std::endl; <-- Fails to compile as planned
std::cout << "stp: " << stp->yyy << std::endl; // ok
std::cout << "bp: " << brp->yyy << std::endl; // ok
}
Unique ownership is unique, full stop. One place owns this resource and will release it when that code so chooses.
Shared ownership is shared. Multiple places can own this resource, and the resource will only be released when all of them have done so. This is a binary state: either one place owns the resource or multiple places do.
Your ownership semantics are unique... except when they're not. And rules that work a certain way except when they don't are kind of problematic.
Now, your specific implementation is full of holes. shared/weak_ptr are all explicitly part of the interface of these types, so it is exceptionally easy to just get the shared_ptr out of a strong_ptr. If you have a weak_ptr to a strong_ptr (required for borrowed_ptr::borrow), then you could just lock it and get a shared_ptr.
But even if your interface were to properly hide all of this (that is, you make your own weak_ptr-equivalent type and you stop inheriting from shared_ptr), your API cannot stop someone from storing that borrowed_ptr anywhere they want. Oh sure, they can't change it later, but it's easy enough to store it in a class member at construction time or to heap allocate one or whatever.
So at the end of the day, locking a weak pointer still represents a claim of ownership. Therefore, the ownership semantics of your pointer stack is still shared; there's simply an API encouragement to not retain shared ownership for too long.
unique_ptr doesn't have "API encouragement"; it has API enforcement. That's what gives it unique ownership. C++ does not have a mechanism to create similar enforcement of the ownership semantics you want to create.
Encouragement may be useful on some level, but it'd probably be just as useful to just have borrowed_ptr as the encouragement for those who want to express that they are only claiming ownership temporarily. And just directly use shared/weak_ptr as normal otherwise. That is, your API should explicitly recognize that it is using shared ownership, so that nobody is fooled into thinking otherwise.

How can I pass a method of an object's class as std::function?

I have a function that needs to get std::function-type parameter. I also have an abstract-type pointer to an object. Is it possible to pass the method using only an object?
The function signature:
void foo(std::function<bool(int i)>);
The classes sample:
class IBase // interface
{
public:
virtual bool sampleMethod(int i) = 0;
};
class Child1 : public IBase // one of the classes that inherit from IBase
{
public:
bool sampleMethod(int i) override;
};
So there is this pointer to an object of one of the Child classes:
std::unique_ptr<IBase> ptr;
And I want to use it to pass the sampleMethod as a parameter of foo.
Is there any way to do it using std or boost?
You can do this with std::bind and a placeholder:
foo (std::bind (&IBase::sampleMethod, ptr.get (), std::placeholders::_1));
You can also use a lambda which captures ptr:
foo ([&ptr] (int i) { return ptr->sampleMethod (i); });
In either case, as Yakk - Adam Nevraumont says, make sure that ptr outlives any references made to it, or copies made of it, in foo.
Live demo
This is C++, so you have to worry about lifetime. Your question completely ignores lifetime; that is a bad thing.
Whenever you talk about anything in C++ you must be clear about the lifetime of everything involved. One way to be clear about it is to talk about ownership. Another is to say one thing is to talk about scope.
The lifetime of:
void foo(std::function<bool(int i)> f);
f and copies of it is not clear. If f and all copies are not going to live past the exit of foo, that is completely different than if f or copies could live past the end of foo.
Part of this is not your fault; the C++ std library lacks a vocabulary type to describe "callable object with no state ownership" (a function_ref), so people use the value-semantics std::function instead.
Supposing what you really want is a function_ref<void(int)>, then you can just do this:
foo( [&](int i){ return ptr->sampleMethod(i); } );
and done; the scope guarantees (ptr outlives the call to foo, and f and its copies will not outlive foo) mean lifetime is accounted for.
If however that foo may keep a copy of f, you have two problems. First, ptr claims unique ownership over the lifetime of *ptr; but f also claims ownership over the object it wants to call.
What more, std::function can be copied; which means either the object it invokes must be copied, or we are forced to have shared ownership.
So after foo does *ptr need to available outside? Do copies of *ptr make sense, or shared ownership between the copies of f of *ptr? More ownership questions, and the answers to them change what the right solution to your problem is.
In a more perfect world, function, moveonly_function, function_ref would all exist, and your choice would inform what you need here and simplify the solition.
I started writing this based on Paul's answer:
_window.setCursorPosCallback(std::bind(&RenderWorld::mouseCallback, this, std::placeholders::_1,std::placeholders::_2));
But clang-tidy told me to change it to this instead:
_window.setCursorPosCallback([this](auto && x, auto && y) {
mouseCallback(std::forward<decltype(x)>(x), std::forward<decltype(y)>(y));
});
So that's kinda cool

clarification of specifics of P0137

In the following code I have been meticulous in the following of the standard's words (plus in the light of the wording of P0137) on object lifetimes.
Note that all memory allocation is through suitably-aligned storage of type unsigned char, as per P0137.
Note also that Foo is a POD, with a trivial constructor.
Questions:
A. If I have misunderstood the standard, and there is any UB here, please kindly point it out (or alternatively confirm that there is no UB)
B. Are the initialisations at A, B, C, D, E, F strictly necessary in light of the fact that the construction is trivial, and performs no actual initialisation. If so, please indicate which part of the standard contradicts or clarifies [object.lifetime] in this regard.
code:
#include <memory>
// a POD with trivial constructor
struct Foo
{
int x;
};
struct destroy1
{
void operator()(Foo* p)
{
// RAII to guarantee correct destruction order
auto memory = std::unique_ptr<unsigned char[]>(reinterpret_cast<unsigned char*>(p));
p->~Foo(); // A
}
};
std::unique_ptr<Foo, destroy1> create1()
{
// RAII to guarantee correct exception handling
auto p = std::make_unique<unsigned char[]>(sizeof(Foo));
auto pCandidate = reinterpret_cast<Foo*>(p.get());
new (pCandidate) Foo(); // B
return std::unique_ptr<Foo, destroy1>(reinterpret_cast<Foo*>(p.release()),
destroy1());
}
struct call_free
{
void operator()(void *p) const { std::free(p); }
};
using malloc_ptr = std::unique_ptr<unsigned char, call_free>;
struct destroy2
{
void operator()(Foo *pfoo) const {
// RAII to guarantee correct destruction order
auto memory = malloc_ptr(reinterpret_cast<unsigned char*>(pfoo));
pfoo->~Foo(); // C
}
};
std::unique_ptr<Foo, destroy2> create2()
{
// RAII to guarantee correct exception handling
auto p = malloc_ptr(reinterpret_cast<unsigned char*>(std::malloc(sizeof(Foo))));
auto pCandidate = reinterpret_cast<Foo*>(p.get());
new (pCandidate) Foo(); // D
return std::unique_ptr<Foo, destroy2>(reinterpret_cast<Foo*>(p.release()),
destroy2());
}
struct nodelete {
void operator()(Foo * p) {
p->~Foo(); // E
}
};
std::shared_ptr<Foo> provide()
{
alignas(Foo) static unsigned char storage[sizeof(Foo)];
auto make = [] {
auto p = reinterpret_cast<Foo*>(storage);
new (p) Foo (); // F
return std::shared_ptr<Foo>(p, nodelete());
};
static std::shared_ptr<Foo> pCandidate = make();
return pCandidate;
}
int main()
{
auto foo1 = create1();
auto foo2 = create2();
auto foo3 = provide();
foo1->x = 1;
foo2->x = 2;
foo3->x = 3;
}
On create1
std::unique_ptr<Foo, destroy1>(reinterpret_cast<Foo*>(p.release()), destroy1());
This doesn't work, because you're using the wrong pointer.
p.release() thinks it points to an unsigned char[]. However, that's not the object you want to point to. What you want to point to is the object that lives inside this array, the Foo you've created.
So you are now subject to [basic.life]/8. The gist of that is that you can only use the previous pointer as a pointer to the new object if they are of the same type. Which they're not in your case.
Now, I could tell you to launder the pointer, but the more reasonable way to handle this is to just store the pointer returned by the placement-new call:
auto p = std::make_unique<unsigned char[]>(sizeof(Foo));
auto ret = std::unique_ptr<Foo, destroy1>(new(p.get()) Foo(), destroy1());
p.release();
return ret;
That pointer will always be correct.
Your use of of placement-new is not optional. [intro.object]/1 tells us:
An object is created by a definition (3.1), by a new-expression (5.3.4), when implicitly changing the active member of a union (9.3), or when a temporary object is created (4.4, 12.2).
When you allocate an unsigned char[], that's the object you have created in that storage. You cannot simply pretend that it is a Foo, just because Foo is an aggregate. [intro.object]/1 doesn't allow that. You must explicitly create that object via one of the mechanisms listed above. Since you can't use a definition, union member activation, or temporary objects with arbitrary memory buffers to create objects from existing storage, the only recourse you have to create objects is a new-expression.
Specifically, placement-new.
As for delete1, you do need a custom deleter, since the default deleter will call delete on the Foo pointer. Your code is as follows:
auto memory = std::unique_ptr<unsigned char[]>(reinterpret_cast<unsigned char*>(p));
p->~Foo();
unsigned char[] has some special logic to it, in terms of how it behaves when objects are allocated in their storage, thanks to [intro.object]/3-4. If the object entirely overlays the storage of the unsigned char[], then it functions as if the object were allocated within the array. That means that the unsigned char[] is still technically there; it has not destroy the byte array.
As such, you can still delete the byte array, which your code here does.
On create2
This is also wrong, due to further violations of [basic.life]/8. A fixed version would be similar to the above:
auto p = malloc_ptr(reinterpret_cast<unsigned char*>(std::malloc(sizeof(Foo))));
auto ret std::unique_ptr<Foo, destroy2>(new(p.get()) Foo(), destroy2());
p.release();
return ret;
Unlike new-expressions, malloc never creates an object via [intro.object]/1; it only acquires storage. As such, placement-new is again required.
Similarly, free just releases memory; it doesn't deal with objects. So your delete2 is essentially fine (though the use of malloc_ptr there makes it needlessly confusing).
On provide
This has the same [basic.life]/8 problems that the rest of your examples have:
alignas(Foo) static unsigned char storage[sizeof(Foo)];
static auto pCandidate = std::shared_ptr<Foo>(new(storage) Foo(), nodelete());
return pCandidate;
But other than that, it's fine (so long as you don't break it elsewhere). Why? That's complex.
[basic.start.term]/1 tells us that static objects are destroyed in the reverse order of their initialization. And [stmt.decl]/4 tells us that block-scoped static objects are initialized in the order they are encountered in a function.
Therefore, we know that pCandidate will be destroyed before storage. So long as you don't keep a copy of that shared_ptr in a static variable, or otherwise fail to destroy/reset all such shared objects before termination, you should be fine.
That all being said, using blocks of unsigned char is really pre-C++11. We have std::aligned_storage and std::aligned_union now. Use them.
If you take seriously Core Issue 1776 and the never voted for idea that "that malloc alone is not sufficient to create an object", then you have to take seriously these ideas:
unions were not usable without UB in C++ until quite recently, as the lifetime of their members was not defined
string literals cannot be examined, as their lifetime is never started
and many other deeper more difficult controversies and contradictions, like what is a lvalue, an object, is lifetime a property of a preexisting object (that exists outside it's life), etc.
Yet I don't see people taking at least the two bullet points seriously. Why would the claim in the DR be taken seriously then?
"Core Issue 1776: Replacement of class objects containing reference members" is based on an obvious and serious interpretation error, and as such should be dismissed. The error is here:
Drafting note: this maintains the status quo that malloc alone is not
sufficient to create an object
This goes against the status quo that "malloc alone" is indeed sufficient to create an object, as malloc returns suitably aligned storage, which is and has always been sufficient to create an object.
A core issue is not the standard. It is an opinion about the standard. That opinion is in error.

C++11 closure shared_ptr

What is the syntax to create heap allocated closure manage by shared_ptr. I want to pass closures to functions and be able to pass nullptr. Seems like using a shared_ptr< ::std::function<void()> but I cannot figure the syntax to initialize that from a lambda expresion
It should be something like
auto lambda = []() { /* do something usefull */ };
auto p = std::make_shared<std::function<void()>>(lambda);
But actually you may no need shared_ptr, since function can be constructed from nullptr.
std::function<void()> fnc(nullptr);
Generally speaking, you want to create a shared_ptr<X> via make_shared, initializing the X object with some Y object. Then generally the code to do that is
auto ptr = make_shared<X>(someY);
In your case, X is the std::function type, and the someY is your lambda. Once you have that, it's pretty straight forward:
auto funPtr = std::make_shared<function<void()>>( [](){ std::cout << "Hello World!\n"; } );
(*funPtr)();
You can do it in two ways:
std::function<void()> lambda = [](){};
auto heapPtr = std::make_shared<std::function<void()>>(lambda);
auto heapPtr2 = new std::function<void()>(lambda);
You might also find the following questions useful:
C++11 lambda implementation and memory model
In C++11 lambda syntax, heap-allocated closures?
I prefer putting shared_ptr inside the function object.
auto o = make_shared<MyData>();
return [o] ()
{
...
};
So, the data for the closure is on the heap and ref-counted while the handle can be copied and passed around. The data is cleaned up when the last handle is destroyed.

Easier way to have shared_ptr own an existing pointer

Many programmers advocate the use of make_shared because it reduces typing and reduces programming errors. However there are some cases where using the constructors of shared_ptr is unavoidable. One of these cases is when you have an existing pointer that you want shared_ptr to own, since shared_ptr<Foo>(&existing_ptr) is bad code. Instead, you have to use the unwieldy shared_ptr<Foo>(shared_ptr<Foo>(), p). Not only are you repeating yourself, but you have to create a temporary object.
int main()
{
using namespace std;
Foo foo;
foo.n = 1;
{
auto ptr = make_shared<Foo>(move(foo));
ptr->n = 42;
cout << ptr->n << " " << foo.n << '\n';
}
{
auto p = &foo;
auto ptr = shared_ptr<Foo>(shared_ptr<Foo>(), p);
ptr->n = 42;
cout << ptr->n << " " << foo.n << '\n';
}
return 0;
}
Foo::Foo()
Foo::Foo(Foo &&)
42 1
Foo::~Foo()
42 42
Foo::~Foo()
What's a less verbose way to have shared_ptr own an existing pointer?
The intended use of that constructor is to allow shared pointers to sub objects of shared pointers.
Your use is not the intended use, and is quite dangerous, as you have implicitly created a guarantee that the data you are passing to the shared pointer will last as long as the shared pointer or its copies does, and then failing to enforce that guarantee in any meaningful sense.
If you pass a shared pointer to a function, it has every right to cache a copy if it and use it 15 minutes later. And if you aren't passing a shared pointer to a function, you don't need one.
In general, a function should only require a shared pointer if it intends to extend the lifetime of its argument in a difficult to predict way. So if you have a function that takes a shared pointer and never extends its lifetime (or the lifetime of a pointer to it), it should not be taking a shared pointer. The problem is in the function you are calling, not with how you have to jump through hoops to call it.
Only when you both have a function that is broken, and are unable to fix it and making a copy of Foo on the free store is overly expensive, is your technique worth trying. And that should be extreme corner cases anyhow.
IMO what you're doing there shouldn't be easy because it's very dangerous, and only necessary under highly specialized circumstances where typing a class name twice should be the least of your worries.
But here is a slightly more succinct way to achieve the same thing by using a dummy deleter:
auto ptr = std::shared_ptr<Foo>(&foo, [](void*){});
Also, in your approach it isn't really correct to say that ptr owns foo; rather it owns the null object in the empty std::shared_ptr<Foo> and points to foo (see this answer for a longer discussion). In my code above it does "own" foo in some technical sense (or at least it thinks it does); it's just been prevented from doing anything to it when its reference count reaches zero.