0

I am wondering whether there is a design pattern that nicely does, what I currently achieve by the following construct:

I have a object that I want to create based on a set of input objects. In my particular case those are stream like objects. During the calculation I need to keep track of so much state, that I do not want to pass it around as function parameters, but also do not want to polute the namespace in which I need the value of the calculation. So what I do is create a class that roughly looks like this:

class objectCreator {
public:
  objectCreator(stream_type & stream) : stream(stream) {
    create();
  }

  std::unique_ptr<value_type> get() { return std::move(result); }

private:

  void
  create() { /* ... */ }

  std::unique_ptr<value_type> result;
  stream_type & stream;

  // various state holding variables
};

My problem is, that clearly calling get() twice does not make sense. I could guard against it, by checking if it has been called already, but I would like to use a construct, that inherently prevents one from calling it twice. (Note: I already wrap this object in a function call somewhere and it should not be used anywhere else, but that's just not beautiful.)

Micha
  • 5,117
  • 8
  • 34
  • 47
  • It seems that you need only one public static method in this class, and don't need parameterized constructor. `get()` can take a `stream_type` as a parameter, and that will be just static factory, and each call of `get()` will return unique object. If you have more public methods in this class, things will be little different, but you should have some flag to see if your object is initialized not only to prevent calling `get()` twice – SpongeBobFan Jun 26 '13 at 07:57
  • But I do need instances of the class. The state of the calculation cannot be kept in static variables. That would cause concurrency problems. The only purpose the static method could serve is already covered by the function that currently encloses the usage of the class. – Philipp Matthias Schäfer Jun 26 '13 at 08:04
  • How many public methods `objectCreator` have? Is it creating object in constructor, and then just store object until someone will call `get()`? Or you call different `objectCreator`'s methods in turn and then call `get()` when it is constructed? If second is true, you can add some variable to keep the state to make it impossible to `get` object that wasn't correctly created, that variable can be set to state "non-constructed" in `get()` function to avoid calling it twice. – SpongeBobFan Jun 26 '13 at 08:28
  • I would use it like this: `auto value = objectCreator(stream).get();`. – Philipp Matthias Schäfer Jun 26 '13 at 08:38
  • What concurrency problems will you have if you'll call it like `auto value = objectCreator.get(stream)` (with static `get()`)? This class don't need anything but one static method if all job is done in just one method (now it's constructor, with static `get()` it will be in that method), so you don't need private variables like `stream_type & stream`. You should always reduce the lifetime and visibility of every variable as possible to avoid mistakes, and those private variables are violating this principle. – SpongeBobFan Jun 26 '13 at 08:54
  • The whole point is, that the job is not done in a single method. It's just one public method. Internally a whole bunch of private methods use member variables to share state (so that I do not need to pass these objects around all the time.) – Philipp Matthias Schäfer Jun 26 '13 at 10:07

1 Answers1

1

Essentially, get() moves-from your object. The best way to let the user do this is require them to move your object before they can call get(). This is done with a rvalue-reference-qualified member function.

std::unique_ptr<value_type> get() && { return std::move(result); }

This has to be called as std::move( obj ).get(). Simply obj.get() wouldn't work.

Of course you never need to move an rvalue so objectCreator( … ).get() on the other hand would work.

Compiler support for this language feature is still arriving, so you might need an upgrade, and/or a port to Clang.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • If you say compiler support is still arriving, does it belong in the realm of 'c++1y'? Could you point me to the document suggesting that language feature (e.g. nXXXX). I like the solution (assuming it is standard compliant at some point), since it would force the caller of `get()` to acknowledge that he knows its a one time thing to do. – Philipp Matthias Schäfer Jun 26 '13 at 07:36
  • 1
    @PhilippMatthiasSchäfer No, this is C++11 and already standardized. I don't have the proposal handy, but it's generally called "rvalue references for this" as well as "reference-qualified member functions." I prefer the latter term because the type or category of `this` never changes. – Potatoswatter Jun 26 '13 at 07:38