#include "cetl/pmr/interface_ptr.hpp"
#include <gtest/gtest.h>
class INamed
{
public:
INamed() = default;
INamed(const INamed&) = delete;
INamed(INamed&& rhs) noexcept = delete;
INamed& operator=(INamed&&) = delete;
INamed& operator=(const INamed&) noexcept = delete;
protected:
~INamed() = default;
};
class IDescribable : public INamed
{
public:
IDescribable() = default;
IDescribable(const IDescribable&) = delete;
IDescribable(IDescribable&& rhs) noexcept = delete;
IDescribable& operator=(IDescribable&&) = delete;
IDescribable& operator=(const IDescribable&) noexcept = delete;
protected:
~IDescribable() = default;
};
class IIdentifiable
{
public:
IIdentifiable() = default;
IIdentifiable(const IIdentifiable&) = delete;
IIdentifiable(IIdentifiable&& rhs) noexcept = delete;
IIdentifiable& operator=(IIdentifiable&&) = delete;
IIdentifiable& operator=(const IIdentifiable&) noexcept = delete;
protected:
~IIdentifiable() = default;
};
class MyObjectBase
{
public:
MyObjectBase()
: id_{counter_++}
{
}
protected:
const std::uint32_t id_;
static std::uint32_t counter_;
friend class example_07_polymorphic_alloc_deleter;
};
class MyObject final : private MyObjectBase, public IIdentifiable, public IDescribable
{
public:
MyObject(const char* name, std::size_t name_length)
: name_{static_cast<char*>(
malloc(name_length + 1))}
{
strncpy(name_, name, name_length + 1);
name_[name_length] = '\0';
}
MyObject(const MyObject&) = delete;
MyObject(MyObject&& rhs) noexcept = delete;
MyObject& operator=(const MyObject&) = delete;
MyObject& operator=(MyObject&&) noexcept = delete;
~MyObject()
{
std::cout <<
"~MyObject(name='" << name_ <<
"', id=" << id_ <<
")" <<
std::endl;
}
std::string name() const override
{
if (name_ == nullptr)
{
return std::string{};
}
else
{
return std::string{name_};
}
}
std::uint32_t id() const override
{
return id_;
}
std::string describe() const override
{
return name() + " is a MyObject instance.";
}
private:
char* name_;
};
class example_07_polymorphic_alloc_deleter : public testing::Test
{
protected:
template <typename Interface>
using InterfacePtr = cetl::pmr::InterfacePtr<Interface>;
void SetUp() override
{
MyObjectBase::counter_ = 0;
}
};
TEST_F(example_07_polymorphic_alloc_deleter, example_usage_0)
{
using MyAllocator = cetl::pmr::polymorphic_allocator<MyObject>;
MyAllocator alloc{cetl::pmr::get_default_resource()};
if (nullptr != object_0)
{
alloc.construct(object_0.get(), "object_0", 8U);
objects.
emplace(object_0->name(), std::move(object_0));
}
if (nullptr != object_1)
{
alloc.construct(object_1.get(), "object_1", 8U);
objects.
emplace(object_1->name(), std::move(object_1));
}
if (nullptr != object_2)
{
alloc.construct(object_2.get(), "object_2", 8U);
objects.
emplace(object_2->name(), std::move(object_2));
}
for (const auto& pair : objects)
{
}
}
TEST_F(example_07_polymorphic_alloc_deleter, example_usage_1)
{
cetl::pmr::polymorphic_allocator<MyObject> alloc{cetl::pmr::get_default_resource()};
auto object_0 = cetl::pmr::Factory::make_unique(alloc, "object_0", 8U);
objects.
emplace(object_0->name(), std::move(object_0));
auto object_1 = cetl::pmr::Factory::make_unique(alloc, "object_1", 8U);
objects.
emplace(object_1->name(), std::move(object_1));
auto object_2 = cetl::pmr::Factory::make_unique(alloc, "object_2", 8U);
objects.
emplace(object_2->name(), std::move(object_2));
auto emplacer = [&objects, &alloc](
const char* name,
std::size_t name_length) {
auto object = cetl::pmr::Factory::make_unique(alloc, name, name_length);
objects.
emplace(object->name(), std::move(
object));
};
emplacer("object_3", 8U);
emplacer("object_4", 8U);
emplacer("object_5", 8U);
for (const auto& pair : objects)
{
}
}
TEST_F(example_07_polymorphic_alloc_deleter, example_usage_2)
{
cetl::pmr::polymorphic_allocator<MyObject> alloc{cetl::pmr::get_default_resource()};
auto obj0 = cetl::pmr::InterfaceFactory::make_unique<MyObject>(alloc, "obj0", 4U);
auto obj1 = cetl::pmr::InterfaceFactory::make_unique<IIdentifiable>(alloc, "obj1", 4U);
{
obj1.reset();
}
auto obj2 = cetl::pmr::InterfaceFactory::make_unique<IDescribable>(alloc, "obj2", 4U);
{
}
auto obj3 = cetl::pmr::InterfaceFactory::make_unique<INamed>(alloc, "obj3", 4U);
{
}
}
{
public:
using ConcreteAllocator = cetl::pf17::pmr::polymorphic_allocator<MyConcreteType>;
friend ConcreteAllocator;
template <typename... Args>
static cetl::pmr::InterfacePtr<cetl::rtti> make(std::allocator_arg_t, ConcreteAllocator alloc, Args&&... args)
{
return cetl::pmr::InterfaceFactory::make_unique<cetl::rtti>(alloc,
std::forward<Args>(args)...);
}
{
return nullptr;
}
{
return nullptr;
}
private:
MyConcreteType() = default;
virtual ~MyConcreteType() = default;
};
TEST_F(example_07_polymorphic_alloc_deleter, example_usage_3)
{
auto dark_ptr = MyConcreteType::make(std::allocator_arg,
MyConcreteType::ConcreteAllocator{cetl::pf17::pmr::get_default_resource()});
static_cast<void>(dark_ptr);
}
#define CETL_NODISCARD
CETL_NODISCARD.
Definition cetl.hpp:203
RAII helper for cetl::pf17::pmr::polymorphic_allocator and std::pmr::polymorphic_allocator.
Definition memory.hpp:136
An alternative implementation of simple runtime type information (RTTI) capability designed for high-...
Definition rtti.hpp:213
virtual CETL_NODISCARD void * _cast_(const type_id &id) &noexcept=0
Implementations can choose to use cetl::rtti_helper instead of implementing this manually.
Extensions and utilities for types found in the standard memory header to better integrate with pmr t...
std::array< std::uint8_t, type_id_size > type_id
A 16-byte UUID (GUID) that uniquely identifies a type.
Definition rtti.hpp:32
CETL polyfill header for C++17 types.