c++classc++14shared-ptrmake-shared

how to block usage of std::make_shared<T>


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.


Solution

  • 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 Ts. 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.