diff --git a/cetlvast/suites/unittest/pmr/test_pmr_interface_ptr.cpp b/cetlvast/suites/unittest/pmr/test_pmr_interface_ptr.cpp index a491dff..cc09968 100644 --- a/cetlvast/suites/unittest/pmr/test_pmr_interface_ptr.cpp +++ b/cetlvast/suites/unittest/pmr/test_pmr_interface_ptr.cpp @@ -235,4 +235,17 @@ TEST_F(TestPmrInterfacePtr, make_unique_myobj_ctor_throws) #endif } +TEST_F(TestPmrInterfacePtr, initially_empty_with_default_deleter) +{ + cetl::pmr::polymorphic_allocator alloc{get_mr()}; + + // 1. Create initially empty interface pointer. + cetl::pmr::InterfacePtr obj0; + EXPECT_THAT(obj0, IsNull()); + + // 2. Now assign a new instance. + obj0 = cetl::pmr::InterfaceFactory::make_unique(alloc, "obj0"); + EXPECT_THAT(obj0, NotNull()); +} + } // namespace diff --git a/include/cetl/pmr/interface_ptr.hpp b/include/cetl/pmr/interface_ptr.hpp index d39d93d..85103e3 100644 --- a/include/cetl/pmr/interface_ptr.hpp +++ b/include/cetl/pmr/interface_ptr.hpp @@ -29,6 +29,12 @@ template class PmrInterfaceDeleter final { public: + /// Constructs empty no-operation deleter. + /// + /// Useful for initially empty `InterfacePtr` instance without deleter attached. + /// + PmrInterfaceDeleter() = default; + /// Constructs a Concrete type-erased deleter for the given interface type. /// /// @tparam PmrAllocator The type of the polymorphic allocator to use for deallocation. @@ -51,7 +57,12 @@ class PmrInterfaceDeleter final /// void operator()(Interface* ptr) noexcept { - deleter_(ptr); + CETL_DEBUG_ASSERT((nullptr != ptr) == static_cast(deleter_), "Empty deleter is fine for null ptr!"); + + if ((nullptr != ptr) && static_cast(deleter_)) + { + deleter_(ptr); + } } // Below convertor constructor is only possible with enabled PMR at `function`. @@ -143,7 +154,7 @@ class InterfaceFactory final using Concrete = typename PmrAllocator::value_type; public: - ConcreteRaii(PmrAllocator& pmr_allocator) + explicit ConcreteRaii(PmrAllocator& pmr_allocator) : concrete_{pmr_allocator.allocate(1)} , constructed_{false} , pmr_allocator_{pmr_allocator}