Hacker News new | ask | show | jobs
by imron 3287 days ago
I agree that 2PI leads to all kinds of pain, but what I meant is not 2PI. Here's a more complete example:

  class Foo
  {
  public:
    static Foo* create()
    {
      Foo* result = new Foo();  //exceptions disabled so new can return nullptr
      if ( result )
      {
        //configure result here
      }
      return result;
    }
  private:
    Foo() {}
  };

  ...
  Foo* badFoo = new Foo(); // compiler error because Foo() is private

  Foo* foo = Foo::create();  //all good, no 2PI and can't forget to call initialize code
  
  if ( foo ) //check for non-null, note, if using an optional you'd also need a similar check
  {
    ...
  }
Now the only way to create a Foo object is through the create() function and there is no separated initialize - it all happens in the same place.

This pattern of using a static create method is explicitly designed to avoid 2PI and is very common, especially in codebases that disable exceptions.

Also note that I'm not personally advocating using it, just that it is commonly used to avoid 2PI.

1 comments

That still means you can't creat instances of Foo on the stack though, doesn't it? Or you can't have a storage or contiguous Foo's (e.g. vector<Foo>)
Correct. It means you can't create instances of Foo on the stack (outside of the Foo class).

You can have contiguous Foos, but not in a vector. You can either have another static function to return an array of Foos, or more commonly have some sort of pool allocator and have the create function allocate objects from the pool.

Anyway, yes, there are limitations for using this pattern, so like all things it's a matter of weighing up the tradeoffs.