Comment

Comment by khold_stare

I completely agree with most of the post. In C++ I use the static factory method "trick" mentioned in the post, when constructing subobjects may throw or result in some kind of error. Throwing from the middle of a constructor in C++ is a quagmire, so it's best not to do it. Bonus, you can mark the constructor and factory functions noexcept.

The part I disagree with relates to "relying on the optimizer for placement". Even in C++ using the above factory pattern, you are returning the constructed object from a function - and there is no problem if it is ultimately part of some larger object. The C++ standard specifies copy-elision very precisely so you don't have to hope the optimizer does it - it is required to. To demonstrate you can do stuff like this even if you object contains non-moveable members, like std::mutex

  class Foo
  {
  private:
    std::mutex mutex_;
    SomeComplexSubObject sub_;

    Foo(SomeComplexSubObject sub) noexcept
      : sub_{std::move(sub)}
    { }

  public:
    static std::optional<Foo> make(SomeParams params) noexcept
    {
      try {
        return Foo{SomeComplexSubObject{params}};
      }
      catch (std::exception const& e) {
        return std::nullopt;
      }
    }
  };
I think Rust can also specify something like this (ie. "copy-elision") as part of its unwritten spec. Anyway, great article! :)
parent khold_stare 7 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton