C++11 make_shared instancing

Viewed 1328

Apologies for the long question, but some context is necessary. I have a bit of code that seems to be a useful pattern for the project I'm working on:

class Foo
{
public:
    Foo( int bar = 1 );
    ~Foo();
    typedef std::shared_ptr< Foo > pointer_type;
    static pointer_type make( int bar = 1 )
    {
        return std::make_shared< Foo >( bar );
    }

...
}

As you can see, it provides a straightforward way of constructing any class as a PointerType which encapsulates a shared_ptr to that type:

auto oneFoo = Foo::make( 2 );

And therefore you get the advantages of shared_ptr without putting references to make_shared and shared_ptr all over the code base.

Encapsulating the smart pointer type within the class provides several advantages:

  1. It lets you control the copyability and moveability of the pointer types.
  2. It hides the shared_ptr details from callers, so that non-trivial object constructions, such as those that throw exceptions, can be placed within the Instance() call.
  3. You can change the underlying smart pointer type when you're working with projects that use multiple smart pointer implementations. You could switch to a unique_ptr or even to raw pointers for a particular class, and calling code would remain the same.
  4. It concentrates the details about (smart) pointer construction and aliasing within the class that knows most about how to do it.
  5. It lets you decide which classes can use smart pointers and which classes must be constructed on the stack. The existence of the PointerType field provides a hint to callers about what types of pointers can be created that correspond for the class. If there is no PointerType defined for a class, this would indicate that no pointers to that class may be created; therefore that particular class must be created on the stack, RAII style.

However, I see no obvious way of applying this bit of code to all the classes in my project without typing the requisite typedef and static PointerType Instance() functions directly. I suspect there should be some consistent, C++11 standard, cross-platform way of doing this with policy-based templates, but a bit of experimentation has not turned up an obvious way of applying this trivially to a bunch of classes in a way that compiles cleanly on all modern C++ compilers.

Can you think of an elegant way to add these concepts to a bunch of classes, without a great deal of cutting and pasting? An ideal solution would conceptually limit what types of pointers can be created for which types of classes (one class uses shared_ptr and another uses raw pointers), and it would also handle instancing of any supported type by its own preferred method. Such a solution might even handle and/or limit coercion, by failing appropriately at compile time, between non-standard and standard smart and dumb pointer types.

3 Answers
Related