Skip to content

Add support for post-construction Init to interface_ptr #156

Description

@thirtytwobits

for systems without exceptions enabled we need a way to call a concrete "init" method after the constructor when using the type-erasers in interface_ptr. The most generalized approach would use a lambda. For example:

    template <typename Interface, typename PmrAllocator, typename... Args>
    CETL_NODISCARD static InterfacePtr<Interface> make_unique_w_initializer(PmrAllocator alloc, std::function<bool(typename PmrAllocator::value_type&)>&& initializer, Args&&... args)
    {
        // Allocate memory for the concrete object.
        // Then try to construct it in-place - it could potentially throw,
        // so RAII will deallocate the memory BUT won't try to destroy the uninitialized object!
        //
        ConcreteRaii<PmrAllocator> concrete_raii{alloc};
        if (auto* const concrete_ptr = concrete_raii.get())
        {
            concrete_raii.construct(std::forward<Args>(args)...);
            if (not initializer(*concrete_ptr)) {
                // Initializer failed. UNDO! UNDO!
                concrete_raii.release();
            }
        }

        // Everything is good, so now we can move ownership of the concrete object to the interface smart pointer.
        //
        return InterfacePtr<Interface>{concrete_raii.release(), PmrInterfaceDeleter<Interface>{alloc, 1}};
    }

Here, the protocol is a pointer is passed into the init method iff allocation succeeds. If the init method returns nullptr then we destroy the object and return a nullptr in the InterfacePtr otherwise we continue normally. Use might look like:

struct MyType : public MyInterface {
    bool Init() {
        return true;
    }
};


auto result = cetl::pmr::InterfaceFactory::make_unique_w_initializer<MyInterface>(concrete_allocator, [](MyType& p) { return p.Init(); });

Additional output from init can be obtained by using the lambda capture. Reliance on the SMO for std::function, of course, applies.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions