Question

Problem

Consider this simple class:

struct C {
   C(const char* name) : name(name) {
         cout << "constructing " << name  << endl;
   }
   
   ~C() {
       cout << "destructing " << name << endl;
   }
   
   string name;
};

I would like to have a pointer to an instance to this class, which is routinely replaced with another instance. However, I would like for the current instance to be destructed before the new instance is created.

Wrong example

If I use a unique_ptr in a normal fashion, this does not work:

unique_ptr<C> c( new C("the first one"));
c.reset(new C("the second one"));

(Undesired) Output:

constructing the first one

constructing the second one

destructing the first one

destructing the second one

Ugly example

The desired effect can be achieved as follows:

unique_ptr<C> c( new C("the first one"));
c.reset();  // explicitly destruct the first one first
c.reset(new C("the second one"));

Output:

constructing the first one

destructing the first one

constructing the second one

destructing the second one

Attempted solution

This is my attempt at creating a smart pointer with this behavior. Does such a smart pointer exist already?

template<typename Resource>
class ResourceManager {
  public:
    ResourceManager() {}

    template<typename... Arguments>
    ResourceManager(Arguments&&... args) {
      replace<Arguments...>(std::forward<Arguments>(args)...);
    }

    template<typename... Arguments>    
    void replace(Arguments&&... args) {
      resource.reset();
      resource.reset(new Resource(std::forward<Arguments>(args)...));
    }

  private:
    unique_ptr<Resource> resource;
};

template<typename Resource, typename... Arguments>
ResourceManager<Resource> make_resource_manager(Arguments... args) {
        return ResourceManager<Resource>(args...);
}

int main() {
   //ResourceManager<C, const char*> r("first1");
   auto r = make_resource_manager<C>("first1");
   r.replace("second1");
}

Output:

constructing the first one

destructing the first one

constructing the second one

destructing the second one

EDIT: Moved 'Arguments...' template to the function level.

EDIT 2: Now forwarding 'Arguments' correctly.

Was it helpful?

Solution

Destroying the old state before constructing the new state is avoided in C++ as much as possible, because one cannot provide the strong exception guarantee that way: "The operation succeeds, or it throws an exception without changing anything". Thus, the standard library does not have such (I cannot even name a framework adding it).

Naive and wrong copy-constructors sometimes do it though.
If you deliberately want to get that behavior, there's nothing better than coding it for yourself.
But, be really sure that's what you want, and document it for posterity.

Your ResourceManager seems mostly to do what you want.
Still, make really sure the method name/class name explicitly calls out your non-standard behavior (neither ResourceManager nor replace are specific enough).

OTHER TIPS

There is nothing like that in the standard. I am not sure why you want that specific order, either the object is still alive and you can reuse it or else you can end up with the new object failing to be constructed and an empty smart pointer.

You could use the ever unpopular in C++ preprocessor:

#define REPLACE_C(ptr,new_value) \
    do { \
        ptr.reset(); \
        ptr.reset(new_value); \
    while(false)

unique_ptr<C> c( new C("the first one"));
REPLACE_C(c, new C("the second one"));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top