
On Feb 1, 2018 7:56 AM, "Emil Dotchevski via Boost"
On 1/02/2018 19:09, Emil Dotchevski wrote:
The factory method technique also allows somewhat restoring a stronger
invariant -- only the constructor and destructor need to cope with empty or otherwise uninitialised instances; other methods can be reasonably assured that no such instances escaped the factory method.
This is true only if you use exceptions to report errors from the factory. Otherwise it is most definitely NOT reasonable for member functions to assume that the object has been initialized, because nothing guarantees that an error reported by the factory wasn't ignored.
The factory itself provides that guarantee. One such pseudo-code implementation might be:
static std::unique_ptr<A> A::create(args...) noexcept { // the constructor is itself noexcept and cannot fail std::unique_ptr<A> a(new (std::nothrow) A(arg1)); if (!a) return nullptr;
if (!a->private_init_stuff(arg2, arg3, ...)) return nullptr;
return a; }
This does not protect the user at all: std::unique_ptr<A> a=A::create(); a->foo(); //undefined behavior Compare to: static std::unique_ptr<A> A::create(args...) { std::unique_ptr<A> a(new A(arg1)); //new throws on error, A::A() throws on error return a; } And then: std::unique_ptr<A> a=A::create(); a->foo(); //Okay, a is guaranteed to be valid. Yeah but you can write stupid code with anything: ``` std::unique_ptr<A> a; try { a =A::create(); } catch (...) {} a->foo(); // ups ```