Please consider the following simplified example:
#include "boost/shared_ptr.hpp"
#include "boost/smart_ptr/enable_shared_from_this.hpp"
using namespace boost;
class State : public boost::enable_shared_from_this<State>
{
public:
shared_ptr<State> GetSelf()
{
return shared_from_this();
};
// returns following state
virtual shared_ptr<State> Execute() = 0;
};
template<typename T>
shared_ptr<T> Create()
{
return shared_ptr<T>(new T);
}
class MyState2;
class MyState1 : public State
{
virtual shared_ptr<State> Execute()
{
if (change of state)
return Create<MyState2>();
else
return GetSelf();
};
};
class MyState2 : public State
{
virtual shared_ptr<State> Execute()
{
if (change of state)
return Create<MyState1>();
else
return GetSelf();
};
};
int main(int argc, char* argv[])
{
shared_ptr<State> pCurrentState = Create<MyState1>(); // <-- OK
// State* pCurrentState(new MyState1); // <-- Runtime error
while (...)
pCurrentState = pCurrentState->Execute();
return 0;
}
The State-class is part of a ‘framework’. It is the base for user defined states in a lightweight state machine, where each state returns its follower state. In case the state does not change, it returns itself. The framework user may arbitrarily derrive from class State. Obviously it is not allowed to create ‘uncontrolled’ instances of derrived classes (would result in runtime error if GetSelf() is invoked). To point the user to the right direction, a Create() function template is provided to create ‘controlled’ instances. Since I want to make usage as foolproof as possible, how can I make sure a user won’t create any instances of derrived states which are not under shared_ptr control? Or at least give a meaningful error message (at compile time?) if he does so.
Thanks for your help!
The simplest way to prevent unmanaged instances is to make the constructor of each derived class private. Your factory function will need to be either a friend or a member of the class it’s creating; if you want to keep your factory template, then it will need to be declared before the derived classes in order to make it a friend:
However, I would usually recommend that you don’t force a class to be managed in a particular way. You should only do something like this if the classes themselves require that they are managed by shared pointers in order to function correctly (that is, they need to call
shared_from_this()from their member functions for some reason). Otherwise, just organise your framework so that it uses shared pointers, and anyone using the framework will have to do likewise with no need for strange enforcement mechanisms. There should be no need forGetSelf()at all, since you’ll always have a shared pointer available to copy if you have access to an object at all, and no need forenable_shared_from_thisunless the classes need to access shared pointers internally (which is rather an unusual thing to do).UPDATE: In your use case, I don’t think it’s possible for the base class to enforce the use of shared pointers (but please correct me if I’m wrong). It might make sense to enforce the use of shared pointers when calling the functions that require them. You’ll be able to create unmanaged objects, but not do anything dangerous with them.