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:
- It lets you control the copyability and moveability of the pointer types.
- 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.
- 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.
- It concentrates the details about (smart) pointer construction and aliasing within the class that knows most about how to do it.
- 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.