I understand why shared_from_this doesn't work in the constructor. I've found a number of posts on here clearly explaining why. I've also seen a workaround for it. My problem is related to this but I'm looking for an elegant workaround.
I quite like this kind of design
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Ptr setA(int) {/* .... */ return this->shared_from_this(); }
Ptr setB(int) {/* .... */ return this->shared_from_this(); }
Ptr setC(int) {/* .... */ return this->shared_from_this(); }
};
so I can daisy chain like this, which I find very readable
Foo::Ptr foo = make_shared<Foo>();
foo->setA(3)->setB(4)->setC(5);
However, my setX methods do more than just assign the value to a property, they might do slightly more complex things (like set other properties etc). So I'd like to use them in my constructor. i.e.
Foo::Foo(int a, int b, int c) {
setA(a);
setB(b);
setC(c);
}
Of course this crashes. However in my case I don't actually need a shared this pointer in my constructor. It's just a side-effect of my wanting to daisy chain later.
A dirty fix could be I just make a bunch of private setX_ methods which do the actual assignment and other tasks, but don't return anything. The constructor calls those. Then I have public setX methods simply call the private ones and then return the this->shared_from_this(). That's safe, but a bit of a PITA. Is it possible to check if a shared pointer to this already exists without crashing? i.e.
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Ptr setA(int) { /*.....*/ return getThis(); }
protected:
Ptr getThis() {
return safe_to_get_this ? this->shared_from_this : Ptr();
}
};
UPDATE
I should have made this clear in my original post, apologies for not doing so. The reason I'm using smart pointers is not so I can do daisy chaining. I usually use references for that if the situation permits.
But in this case Foo (and other classes) belong to a graph like structure, they have dependencies on each other, multiple parent-child-sibling relationships etc. So I use a mix between shared and weak pointers. But I need the methods to return shared_ptrs, so I can cast to weak or check against null if need be (They are created with factory methods, and there are find/get methods too which need checking against null). Basically it's a physics system with different types of particles and constraints between particles. I originally wrote this with my own smart pointer implementation many years ago, and now I'm upgrading it to c++11. I could make the setX methods return references, and have a single getThis() method return the shared pointer (which is what I was doing before), but then I'm worried it becomes a bit inconsistent with some methods returning smart pointers others returning references.
Foo::Ptr foo = World::create();
foo->setA().setB().setC();
foo = World::find(...);
if(foo) foo->setA().setB();
I just prefer the consistency of always returning pointers, as opposed to sometimes pointers and sometimes references. Unless there is a strict guideline for this that can be summarized succinctly.
UPDATE2
This is the (not very elegant) workaround I'm using currently. I was just wondering if there was a way of doing this without manually keeping track of _isInited;
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Foo() {
_isInited = false;
setA();
setB();
setC();
_isInited = true;
}
Ptr setA(int) {/* .... */ return getThis(); }
Ptr setB(int) {/* .... */ return getThis(); }
Ptr setC(int) {/* .... */ return getThis(); }
protected:
bool _isInited;
Ptr() {
return _isInited ? this->shared_from_this() : Ptr();
}
};
I'd like to add to the correct comment by #JoachimPileborg. I don't think your problem really has to do with the technicalities of an aspect of how to use enable_shared_from_this, but rather when to use (smart) pointers.
Consider the following code, showing two ways to use chained calls:
struct ptr_foo
{
ptr_foo *set_x(int x) { return this; }
ptr_foo *set_y(int y) { return this; }
};
struct ref_foo
{
ref_foo &set_x(int x) { return *this; }
ref_foo &set_y(int y) { return *this; }
};
int main()
{
ptr_foo pf;
pf.set_x(0)->set_y(1);
ref_foo rf;
rf.set_x(0).set_y(1);
return 0;
}
The first class, ptr_foo, uses raw pointers, and the second one, ref_foo, uses references.
To begin with, the second invocation,
rf.set_x(0).set_y(1);
seems to me much more consistent than the first one,
pf.set_x(0)->set_y(1);
for the common case of stack-based objects.
Furthermore, even if you prefer the first one, I don't think there's any reason to return a smart pointer, as
no allocation is taking place
the protocol is not meant for obtaining a store-able pointer to a ptr_foo by calling set_?; if someone does so, it is an abuse of the protocol, as it is just meant for chained calles.
Regarding point 2, you can't shut down protocol abuses hermetically anyway. E.g., consider
ptr_foo pf;
ptr_foo *ppf = &pf;
No matter how you design ptr_foo, the user now holds a pointer to an object of that type, which was not allocated dynamically, and which can be erroneously erased.
Related
We can use nodiscard attribute to imply that the return value of a function should not be discarded. Are there any attribute (or other ways) to imply some opposite semantics: the return value of the function should only be used temporarily (by "temporary" I mean, not to assign to any variable except local ones)?
As the purpose may not be immediately clear, consider I have a class FooHolder that holds resources Foo; calling FooHolder::getFoo() returns the Foo it is currently holding:
#include <memory>
class Foo {
public:
Foo& bar() { /* do something */ return *this; }
const Foo& far() const { /* do something else */ return *this; }
};
class FooHolder {
private:
std::shared_ptr<Foo> _foo { nullptr };
public:
FooHolder(): _foo(std::make_shared<Foo>()) {}
Foo& getFoo() { return *_foo; }
const Foo& getFoo() const { return *_foo; }
};
And we may use it in many ways:
// Others may try storing some status:
Foo* g_foo = nullptr;
int main() {
FooHolder foo_holder {};
// I want to support this:
foo_holder.getFoo().bar().far() /* chained calls... */ ;
// Also, maybe this:
auto& local_foo = foo_holder.getFoo();
local_foo.bar();
local_foo.far();
// But not this, because the Foo instance that FooHolder holds may perish:
static Foo& static_foo = foo_holder.getFoo();
// Nor this:
g_foo = &local_foo;
return 0;
}
So are there ways to prevent (or at least warn about) storing the return value of FooHolder::getFoo()? Or, is it bad practice to return resources by reference?
[...] is it bad practice to return resources by reference?
It depends. There are many examples of methods that return non-const references and they are all fine. For example consider standard container element accessors. However, they are not meant for encapsulation. std::vector::operator[] is not meant to hide the elements from the caller, it is meant to provide direct access to it. Returning a non-const reference is not encapsulation! It is the opposite. Note that std::vector even grants you access to its data(). Thats not encapsulation either, it is relying on the user to not delete[] some_vect.data() or do other wrong stuff that would break the vector.
You want FooHolder to encapsulate the contained Foo.
This is opposing requirements.
You have basically two choices: A) The caller knows what they are doing. They read documentation. They know that they are not supposed to use FooHolder::getFoo in the wrong way. B) use proper encapsulation: Never give the caller direct access to a non-const Foo:
class FooHolder {
private:
std::shared_ptr<Foo> _foo { nullptr };
public:
FooHolder(): _foo(std::make_shared<Foo>()) {}
// nope // Foo& getFoo() { return *_foo; }
// maybe // const Foo& getFoo() const { return *_foo; }
FooHolder& bar() {
_foo->bar();
return *this;
}
// ..same for far() ...
};
Note that A) is a viable solution. Consider that also things like std::shared_ptr can be used terribly wrong. Users are expected to know how to use it right. The difference is that std::shared_ptr is a standard type with plenty of documentation. Hence, you should think twice if this is the way to go.
So are there ways to prevent (or at least warn about) storing the return value of FooHolder::getFoo()?
No. Once you returned a non-const reference all bets are off. FooHolder is no longer in control of what the caller can do with that reference. You can prevent copies or moves but you cannot prevent holding on to a reference.
I'm in the situation where I'm not sure which type of smart pointer to use because I'm not sure of all the use cases for my class. I could just use shared pointers but I'm not fond of the idea of passing shared pointers everywhere in my code when I don't necessarily need shared ownership. This article by Herb Sutter says that when in doubt, use unique_ptr and convert to shared_ptr when you have to. This is what I'd like to do but I'm unclear as to how this is supposed to be done, consider this example:
class Example
{
public:
Example(): _ptr(std::make_unique<Node>()) {}
std::unique_ptr<Node>& getPtr()
{
return _ptr;
}
private:
// I am unsure if I will eventually need shared ownership or not
std::unique_ptr<Node> _ptr;
};
Example* example = new Example();
// Some function somewhere
void f()
{
// I've decided I need shared ownership, converting
std::shared_ptr<Node> ptr(std::move(example->getPtr()));
// Oops, example is no longer valid...
}
If someone has a better idea of how to deal with situations like this I'd be glad to hear it.
I think you are asking a kind of optimization question. You want Example to use unique_ptr because it has simpler and more efficient semantics (paraphrasing your referenced article). But, when the need arises, you wish to allow the pointer to be converted to shared_ptr.
Example should simply provide an interface for that, and itself needs to convert from unique_ptr to shared_ptr, when its user invokes that interface. You could use state pattern to capture whether the instance is in unique_ptr mode or shared_ptr mode.
class Example
{
struct StateUnique;
struct StateShared;
struct State {
State (std::unique_ptr<State> &s) : _state(s) {}
virtual ~State () = default;
virtual Node & getPtr () = 0;
virtual std::shared_ptr<Node> & getShared() = 0;
std::unique_ptr<State> &_state;
};
struct StateUnique : State {
StateUnique (std::unique_ptr<State> &s)
: State(s), _ptr(std::make_unique<Node>()) {}
Node & getPtr () { return *_ptr.get(); }
std::shared_ptr<Node> & getShared() {
_state = std::make_unique<StateShared>(*this);
return _state->getShared();
}
std::unique_ptr<Node> _ptr;
};
struct StateShared : State {
StateShared (StateUnique &u)
: State(u._state), _ptr(std::move(u._ptr)) {}
Node & getPtr () { return *_ptr.get(); }
std::shared_ptr<Node> & getShared() { return _ptr; }
std::shared_ptr<Node> _ptr;
};
public:
Example(): _state(std::make_unique<StateUnique>(_state)) {}
Node & getNode() { return _state->getPtr(); }
std::shared_ptr<Node> & getShared() { return _state->getShared(); }
private:
std::unique_ptr<State> _state;
};
If the state machine looks scary (which it should, since it is over-engineered), then you can just maintain two pointers in the Example, and your methods which need to test which one it needs to use.
class Example
{
public:
Example(): _u_node(std::make_unique<Node>()) {}
Node & getNode() { return _u_node ? *_u_node.get() : *_s_node.get(); }
std::shared_ptr<Node> & getShared() {
if (_u_node) _s_node = std::move(_u_node);
return _s_node;
}
private:
std::unique_ptr<Node> _u_node;
std::shared_ptr<Node> _s_node;
};
If you have a class, say UniqueResourceHolder, it may be implemented as follows:
class UniqueResourceHolder{
public:
std::unique_ptr<Widget> ptr;
};
Later, if you want to get said resource from UniqueResourceHolder and put it in a SharedResourceHolder that looks as follows:
class SharedResourceHolder{
public:
std::shared_ptr<Widget> ptr;
};
the code to do so may look like this:
{
UniqueResourceHolder urh;
SharedResourceHolder srh;
//initialization of urh.ptr
srh.ptr = std::shared_ptr<Widget>(urh.release());
}
UniqueResourceHolder will no longer have the Widget it once did, so any attempt to use urh to get at the widget will be invalid (unless you repopulate it with a new one), but srh now will have that widget and will be willing to share. Anyway, that's how I understand the answer to the question in the link you provided. My own two cents is that it is also a trivial matter to replace occurrences of std::unique_ptr with std::shared_ptr; any business logic your program followed to ensure the uniqueness of the resource is still valid, but to go from business logic where you took advantage of the shared-nature of std::shared_ptr would take some time and focus to rework to a unique mindset.
Shared pointers are for shared resources. If you want to share resources I would declare everything shared from the beginning and not go through special conversions.
If you want to use unique pointer you are saying that there "must" only exist one pointer for the the resource you have allocated. That does not limit your way in using these objects. Why not rather use unique pointer and "move" your object through the classes instances and functions... If you have to convert to your pointer why not move it as unique...
Regarding performance: It is said, that compared to a primite pointer, the shared pointer is about 6 times slower. The unique pointer is about twice as slow. Of course I'm talking about accesses. If you really have performance critical portions of the code you can still get primitive pointers of these classes and operate. It does not even have to be a pointer, there are still the C++ References.
I think you should decide whether your object will be "shared" or "moved" and go on with the paradigm, instead of converting and changing all the time.
std::unique_ptr<Node>& getPtr()
{
return _ptr;
}
No, no. You are passing multiple references if you call that from different places. Use the "move" operator instead (With declarations like type& operator=(type&& other) for example) and pass your unique pointer.
I m writing a library.
WITHOUT using smart pointer. Is it this class safe enough to emulate retain/release behaviour?
Or is there any library already doing things like this?
class FooBase {
private:
std::atomic<uint32_t> m_retainCount;
public:
FooBase()
{
m_retainCount = 1;
};
virtual ~FooBase()
{
assert(m_retainCount == 0); // Prevent from direct delete without release()
//clean-up if any
};
void *release()
{
m_retainCount--;
if (!m_retainCount)
delete this;
return this;
};
void *retain()
{
m_retainCount++;
return this;
};
};
Imagine if your thread gets swapped right after the branch in release and before the call to delete.
Another thread could come and request a retain, therefore obtaining a pointer to a soon to be deleted object.
To answer the second part, std::shared_ptr is thread-safe. It has the additional benefit of being able to use non-portable tricks internally because it's formally part of the compiler.
I'd like to know is it better to specify a default initialization for a smart-pointer or do a NULL value check before accessing the smart-pointers methods?
Currently I've been using the method below to avoid calling increment() on a NULL pointer. Is this a reasonable way of doing things or is there a pitfall that I don't see?
Note: We use a custom smart-pointer class and I don't have the Boost libraries on my current configuration to test compile this code. This should compile, but YMMV.
Example.h
#include <boost/shared_ptr.hpp>
class Foo
{
public:
Foo() : mFoo(0) {}
Foo(int rawValue) : mFoo(rawValue) {}
void increment() { mFoo++; }
private:
int mFoo;
};
typedef boost::shared_ptr<Foo> FooSP;
class MyClass
{
public:
MyClass() : mFoo(new Foo()) {}
FooSP foo() { return mFoo; }
void setFoo(FooSP newFoo) { mFoo = newFoo; }
private:
FooSP mFoo;
};
Main.cpp
#include <Example.h>
int main()
{
MyClass temp; // Default-constructed
temp.foo()->increment(); // Increment Foo's member integer
// Before: mFoo = 0
// After: mFoo = 1
FooSP tempFoo = new Foo(10); // Create a Foo with a default size
temp.setFoo(FooSP(new Foo(10))); // Explicitly set the FooSP member
temp.foo()->increment(); // Increment the new FooSP
// Before: mFoo = 10
// After: mFoo = 11
return 0;
}
If you are using a smart pointer as a general replacement for a pointer type, you cannot get away from a check for null. This is because a class defined with a smart pointer with a default constructor is likely to allow the smart pointer to be created with its default constructor. Dynamically creating a new object just to fill the pointer until you can set it seems to be a waste of resources.
shared_ptr's constructor is explicit, so your initialization of tempFoo won't compile. If you wanted to save a line of code, you can avoid declaring the temporary like this:
temp.setFoo(FooSP(new Foo(10)));
You can also declare the method of setFoo to take a constant reference, to avoid manipulating the reference count when taking in the parameter.
void setFoo(const FooSP &newFoo) { mFoo = newFoo; }
Or use swap on the parameter instance.
void setFoo(FooSP newFoo) { std::swap(mFoo, newFoo); }
If I were required to implement something along the lines of what you are proposing, I would create a static instance of Foo to serve as the null version, and then have the increment method throw an exception if it was the null version.
class Foo
{
public:
static Foo Null;
//...
void increment() {
if (this == &Null) throw Null;
mFoo++;
}
//...
};
struct DeleteFoo {
void operator () (Foo *t) const {
if (t != &Foo::Null) delete t;
}
};
class MyClass
{
public:
MyClass() : mFoo(&Foo::Null, DeleteFoo()) {}
//...
};
Note the custom deleter for FooSP to properly deal with Foo::Null.
is it better to specify a default initialization for a smart-pointer or do a NULL value check before accessing the smart-pointers methods?
There is no right answer which applies to every case (more soon). If I had to err to one or the other, I would err toward NULL testing without default initialization because that's an obvious programmer error which can be detected and corrected easily.
However, I think the right answer is that there are good reasons we use multiple idioms for construction and initialization, and that you should choose the best approach for your program.
Typically, I will be explicit (no default or no default initialization) in the lower level classes, as well as complex higher level classes. When the classes are mid-level and defaults and ownership are more obvious (often because of limited use cases), then a default may be sensible.
Often, you will just want to be consistent, to avoid surprising clients. You'll also need to be aware of the complexity of allocating default-initialized objects. If it's big and complex to create, and a default does not make sense, then you are simply wasting a lot of resources when the default-constructed object is the wrong choice.
a) do not apply a default where it does not make sense. the default should be obvious.
b) avoid wasted allocations.
In addition to the approaches you have mentioned, there are a few other angles you might also consider:
Matching Foo's declared constructors in MyClass. At least, the ones which pertain to MyClass.
If copyable and efficient to copy, passing a Foo to MyClass's constructor.
Passing Foo in a container (smart pointer in this case) to MyClass's constructor to remove any ambiguity and to offer the client the option to construct (and share, in the case of a shared pointer) Foo as they desire.
Is this a reasonable way of doing things or is there a pitfall that I don't see?
Wasted allocations. Surprising results. It can restrict capabilities. The most obvious, broadly applicable problems are time and resource consumption.
To illustrate some scenarios:
say Foo reads a 1MB file every time it is constructed. when construction parameters are necessary and the default is not the right option, the file would have to be read a second time. the innocent default would double the disk io required.
in another case, an omitted construction parameter may be another large or complex shared pointer. if absent, Foo may create its own -- when the resource could/should have been shared.
Constructors parameters are often very important, and often should not be erased from the interface. It's certainly fine to do so in some cases, but these conveniences can introduce a lot of restrictions or introduce much unnecessary allocations and CPU time as the contained object's complexity increases.
Using both approaches in your programs is fine. Using additional approaches I outlined is also fine. Specifically, using the right approach for the problem is ideal - there are multiple ways to implement ideal solutions available; you just have to determine what that is in the context of what it is your program is trying to do. All these approaches have separate pros and cons - there is often an ideal match for the context of your program's operation and exposed interfaces.
I have a question similar to How to manage object life time using Boost library smart pointers? but, in my case, the "object" isn't a C++ object at all, but an opaque type returned/passed out from a C API. The type does not have pointer semantics, i.e., there is no dereferencing; it is, however, passed as an argument to other functions in the C API. The type also has a definitive close API which must be called in order to clean up internal resources.
So, I have a C API that's something along the lines of
opaque_legacy_type_t x;
XXopen(..., &x); // allocates/opens resource and fills out 'x' to be used later
XXdoSomethingWithResource(x, ...); // do something with resources related to 'x'
...more actions...
XXclose(x); // closes and cleans up resources related to 'x'
For various reasons, in my C++ code I would like to manage "instances" of opaque_legacy_type_t much like I would manage heap-allocated object instances, i.e. with similar sharing semantics as boost::shared_ptr<>. It seems that shared_ptr offers enough that I can manage calling XXclose by doing this:
opaque_legacy_type_t x;
XXopen(..., &x);
boost::shared_ptr<opaque_legacy_type_t> managed(x, XXclose);
But, since opaque_legacy_type_t doesn't have pointer semantics, the usage of managed is a bit clumsy.
What I'd like to do is have something like a managed_type that is similar to shared_ptr, and am looking for ideas that don't require me to write it all.
EDIT: I corrected my original screw-up in the example. The legacy API takes the opaque type by value rather than by pointer.
Since all of the legacy API take a pointer to the opaque type, you could use shared pointers directly. The key is for you to not declare the original structure on the stack, but rather allocate it via new:
int main () {
std::shared_ptr<opaque_legacy_type_t> x(new opaque_legacy_type_t,
[](opaqeue_legacy_type_t* p) { XXClose(p); delete p; });
XXopen(..., x.get());
XXdoSomethingWithResource(x.get(), ...);
}
EDIT: If some API take the opaque type by value instead of pointer, then pass the dereferenced pointer.
int main () {
std::shared_ptr<opaque_legacy_type_t> x(new opaque_legacy_type_t,
[](opaqeue_legacy_type_t* p) { XXClose(*p); delete p; });
XXopen(..., x.get());
XXdoSomethingWithResource(*x, ...);
}
You could use boost smart pointers together with the pimpl idom:
class shared_opaque_legacy_type_t {
struct impl {
opaque_legacy_type_t t;
impl(...) { XXOpen(..., t); }
~impl(...) { XXClose(t); }
}
boost::shared_ptr<impl> _impl;
public:
shared_opaque_lagacy_type_t(...) : _impl(new impl(...)) {}
opaque_legacy_type_t* get() {
return _impl->t;
}
};
shared_opaque_legacy_type_t x(...);
XXdoSomethingWithResource(x.get(), ...);
The drawback is that you could still call XXclose(x.get()) and invalidate your object.
UPDATE: Fixed it. :-)
You could write a wrapper to use with boost that will call the open() in the ctor and the close() in the dtor.
I voted for Rob's answer that just uses a shared_ptr with no wrapper, but if you really want to avoid dynamic allocation here's a simple little example of how to do that.
It's a template that directly holds the handle and does no allocation. You pass the constructor a functor that creates an object of the opaque type, and a deleter to call when the type needs to be destroyed. It's movable and non-copyable so now shared reference count is needed. It implements implicit conversion operators so you can use it where you'd use a value of the held type.
template<typename T,typename D>
class opaque_type_handle {
T handle;
D deleter;
bool needs_delete;
public:
template<typename F>
opaque_type_handle(F f,D d) : handle(f()), deleter(d), needs_delete(true) {}
opaque_type_handle(opaque_type_handle const &) = delete;
opaque_type_handle &operator=(opaque_type_handle const &) = delete;
opaque_type_handle(opaque_type_handle &&rhs) : handle(rhs.handle),deleter(rhs.deleter),needs_delete(true) {
rhs.needs_delete = false;
}
opaque_type_handle &operator=(opaque_type_handle &&rhs) {
handle = rhs.handle;
deleter = rhs.deleter;
needs_delete = true;
rhs.needs_delete = false;
returh *this;
}
~opaque_type_handle() {
if(needs_delete) {
deleter(handle);
}
}
operator T&() { return handle; }
operator T() const { return handle; }
};
Use it like so:
// wrap up the code for creating an opaque_legacy_type_t handle
typedef opaque_type_handle<opaque_legacy_type_t,decltype(&XXclose)> legacy_handle;
legacy_handle make_legacy_handle(...) {
return legacy_handle(
[](){
opaque_legacy_type_t tmp;
XXopen(..., &tmp);
return tmp;
},
&XXclose
);
}
legacy_handle x = make_legacy_handle(...);
XXdoSomethingWithResource(x,...);