News for hackers. Stuff that matters.
Re:Show HN: Crown – A flexible game engine written from scra... by imron on Thursday June 22, 2017 @11:16AM (#14612811)
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.

Re:Show HN: Crown – A flexible game engine written from scra... by maccard on Friday June 23, 2017 @09:22AM (#14618942)
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>)
Re:Show HN: Crown – A flexible game engine written from scra... by imron on Friday June 23, 2017 @11:10AM (#14619707)
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.