steffen
steffen

Reputation: 8968

How to ensure that there is at least one instance of a class?

I need to ensure that there is at all times during programm execution at least one instance of a certain class. A Singleton won't do because (among other reasons) I might in the future need more instances. A static class might as well do but that feels like going global... Also I would like some private members, both functions and variables.

I thought about keeping a shared_ptr somewhere safe, but that seems to be a rough hack.

Is there a standard way to do this?

edit

To clarify: it is not a matter of being able to check whether an instance still exists. An instance must exist at all times. The reason is that there are static member variables in the class, which should maintain their state.

Upvotes: 2

Views: 212

Answers (4)

utnapistim
utnapistim

Reputation: 27385

I need to ensure that there is at all times during programm execution at least one instance of a certain class.

So I guess the solution begins with deciding who is responsible for storing it.

You could: store it internally within the class (static) or return it to the caller/client context (and rely on the client context to keep it). Since you say "A Singleton won't do" the solution should look like this:

class TheClass
{
public:
    // this doesn't have to be a std::shared_ptr<WithContext>
    // and probably shouldn't be (see below)
    typedef <implementation-defined> GlobalContext;

    GlobalContext InitContext(); // return instance
};

void main( /* ... */ )
{
    // do this before any code that uses TheClass instances
    auto global_execution_context = TheClass::InitContext();

    // rest of your application code goes here
}

I thought about keeping a shared_ptr somewhere safe, but that seems to be a rough hack.

What do you see as it's drawbacks? If it's because it's an obscure dependency, you can add a test for it, or throw an exception when the context is deleted/affected/not there. You could also ask for a reference to your context in TheClass' constructor.

The reason you shouldn't have GlobalContext be a std::shared_ptr but it's own type, is that this is what your requirements actually amount to:

you need a (new) type of object that keeps common state of TheClass between instances.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409404

How about a kind of factory class, that contains a collection of all the instances?

Something like:

template<typename T>
class least_one_factory
{
    static std::vector<T> instances_;

public:
    least_one_factory()
    {
        // Make sure there is an instance of `T` in our collection
        instance_.push_back(T());
    }

    T& get()
    {
        return instances_.front();
    }

    T& get(int n)
    {
        return instances_.at(n);
    }

    T& create()
    {
        instances_.push_back(T());
        return instances_.back();
    }

    int count() const
    {
        return instances_.size();
    }

    operator T&()
    {
        return get();
    }
};

template<typename T>
std::vector<T> least_one_factory<T>::instances_;

Now you can do:

struct some_class {};

least_one_factory<some_class> some_class_factory;

The variable some_class_factory will contain at least one instance of some_class. You can get it with some_class_factory.get(). If some_class_factory is a global variable, then the instance of some_class will be created when your program is loaded before main is called.

Upvotes: 1

masoud
masoud

Reputation: 56519

Use a static member and set it in constructor/destructor:

class Test
{
  static int i;
public:
  Test()
  {
    i++;
  }

  Test(const Test &t) // It's suspicious 
  {
    i++;
  }

  ~Test()
  {
      i--;
  }

  static bool hasInstance()
  {
    return i>0;
  }
};

static int Test::i = 0;

Then, you know if Test has any instance or not.

Upvotes: 1

Roman Nikitchenko
Roman Nikitchenko

Reputation: 13046

I always implement this using internal static counter which was incremented in constructor and decremented in destructor.

And yes, definitely you method to check 'at least one instance' should be static.

UPDATE: OK, I see errors in answers here so I post my answer:

class Test
{
private:
  static int m_count;
public:
  Test() { ++m_count; }
  Test(const Test&) { ++m_count; }

  ~Test()
  {
    --m_count;
  }

  static bool hasInstance()
  {
    return (m_count > 0);
  }
};

int Test::m_count = 0;

int main()
{
    return 0;
}

Upvotes: 1

Related Questions