Anubhav asked:
An interesting question has come up in our project while debating operator new as a class member function. Specifically, the question is about whether such a class should be allowed to be instantiated on stack. The understanding is that a class providing its own operator new would likely have special layout considerations which would not be met if the object of such a class is instantiated locally.
The class specific operator new is used when allocating on the heap, but objects can still be allocated on the stack. The only way I know to prevent an object from being instantiated on the stack is by forcing creation through a factory function that always allocates on the heap, for example:
#include <memory>
class X {
// make all ctors private
X();
X(const X&);
// and any other ctors go here
public:
// Factory function (or it could be a nonmember friend)
static auto make( /*…*/ ) { return std::unique_ptr<X>(new X( /*…*/ )); }
// the usual public member functions go here
};
int main()
{
X x; // error
auto x2 = X::make(); // ok
}
My idea is a wrapper around. Is there any issues?
@Grout: Deriving from
enable_shared_from_this
doesn’t actually block compilation of code that instantiates the object on the stack. Nor does it block compilation ofnew Foo()
. I have found thePrivateConstructorTag
to be the best way to ensure that a class that inherits fromenable_shared_from_this
is only constructed withmake_shared()
.If
is the plan anyway, then deriving from
may be adequate. No?
Hi. Does
std::make_unique
have the same problems with the private constructor pattern asstd::make_sharedcode> have? I.e. that it is not portably possible to make
std::make_shared
a friend ofX
in the example. What is the preferred way to solve this problem? Is the use of thePrivateConstructorTag
the only way?Correction:
should be
@Good point, thanks. Fixed.
But this also gives up on the perf and memory layout advantages of std::make_shared… In library code this could be premature pessimisation. What about:
class X
{
//make all ctors private
struct PrivateConstructionTag {};
public:
static auto make( /*…*/ ) { return std::make_shared( /*…*/ PrivateConstructionTag()); }
};
I’m using this pattern in my library code. Is this the best solution?
@mttpd: The protected destructor solution also works, but it’s a C++98 idiom that’s now inferior because it requires using a custom ‘deleter’ function that is possible, but less natural and idiomatic in modern C++, to use together with unique_ptr and shared_ptr.
@Petter: Good point, thanks. Fixed.
But std::make_unique also requires access to the constructor, right? X::make could create the unique_ptr manually instead.
How about the protected destructor solution?
For instance, as suggested here:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Requiring_or_Prohibiting_Heap-based_Objects