I know I can prevent ordinary heap allocation of custom class and its descendants by making the class's operator new
private, but is there any way to prevent a user of a library from calling std::make_shared
on a custom class (or its descendants)? Apparently, simply making the operator new
private in a class does not stop it.
Note that I do not want to completely prevent shared pointers from being created by any means, as I intend to still be able to produce a std::shared_ptr
for my custom class by calling a static generator method, but I still want to prevent others from trying to call std::make_shared
on my class directly.
EDIT:
To address queries below, my ultimate goal here is a flexible and reusable mechanism for extracting a shared_ptr from a raw pointer. std::enable_shared_from_this
is regretfully not very friendly when it comes to inheritance and especially multiple inheritance.
Also, because I am intending for this to be used as in a template class using CRTP, it would complicate matters somewhat for the a child class T to need to explicitly make the templated parent class it inherits from a friend so that it can access otherwise private constructors.
Blocking user heap allocation of a type T
is not actually a thing you can do in C++. At least, not so long as they can create T
s. Even if you manage to forbid make_shared<T>
, your user can still do this:
unique_ptr opt = new optional<T>;
opt->emplace(...);
The T
inside of *opt
is definitely on the heap. Any number of other similar gymnastics can achieve the same effect. You can even call make_shared<optional<T>>
, with the in_place
parameters.
So long as T
has publicly accessible constructors, or there is any publicly accessible way of constructing a T
that returns a prvalue of it, users can find ways to store that T
on the heap.
So the only way to prevent this is to make all of your constructors private (whether directly with private
or a private
key type or whatever other mechanism you want) and only provide publicly accessible functions that return shared_ptr<T>
s.
Outside of macros, there is no C++ mechanism that just causes a type to work this way. It must be done individually, for each type that you want to work this way.