mercredi 23 novembre 2016

Single-use Class Idiom?

There are times where you want to execute logic on some data once and only once per instance of that data. To my knowledge there is no such pattern (let alone idiom) for accomplishing this.

There is the std::call_once() but that only ensures something is executed once per process instance. Even if the std::once_flag could be used as a class data member it would simply ensure the function is only called once at runtime rather than trying to enforce it at compile time.

Enter the Single-use class:

class single_use_key {
public:
  single_use_key() : _self(new model_t()) {}
private:
  struct model_t {

  };

  std::unique_ptr<const model_t> _self;
};

class consumer_object {
public:
  consumer_object(single_use_key key) : _self(std::make_shared<const model_t>(std::move(key))) {}
private:
  struct model_t {
    model_t(single_use_key key) : _key(std::move(key)) {}
    single_use_key _key;
  };

  std::shared_ptr<const model_t> _self;
};

single_use_key key;
consumer_object consumer(key); // Error
consumer_object consumer(std::move(key)); // OK

This idiom ensures that the class instance is used only once since it can only be moved and not copied.

If you wanted to try and use the object more than once you would have to reference it after you promised you would not (since std::move() was called). Even if you did this, the consumer class/function could be setup to ignore it just like how std::call_once() does because std::unique_ptr<> is guaranteed to be nulled after std::move().

Do you see any problems with this idiom? Is there already something like this that I simply have not found yet? (Or perhaps I am stating something so obvious no one has ever bothered to document it...)

Aucun commentaire:

Enregistrer un commentaire