HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Vector of derived classes

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
derivedvectorclasses

Problem

Everyone knows you can't put a Derived in an std::vector. I decided to implement a collection which does allow you to do this:

```
#pragma once
#include
#include
#include

template
class DerivedVector {
struct Block;
public:
using value_type = T;
using reference = T&;
using const_reference = T const&;
using pointer = T*;
using const_pointer = T const*;

private:
struct TypeInfo {
using deleter_t = void()(void);
deleter_t deleter;
using mover_t = void()(Block&, void);
mover_t mover;
};

template
struct TypeInfoImpl {
static_assert(std::is_destructible::value, "Derived class not destructible");
static_assert(std::is_move_constructible::value, "Derived class not move-constructible");
static_assert(std::is_base_of::value, "Class is not derived");
static_assert(sizeof(D) (p)->~D();
}

static void mover(Block& p, void* o) {
new (p.data()) D(std::move(*static_cast(o)));
}

static TypeInfo* get() {
static TypeInfo info{deleter, mover};
return &info;
}
};

struct Block {
using element_type = T;
TypeInfo* info = nullptr;
typename std::aligned_storage::type storage;

Block() = default;

template::type>::value>::type>
Block(D&& d) {
construct(std::forward(d));
}

Block(Block&& b) : info(b.info) {
if (info)
info->mover(*this, b.data());
}

Block& operator=(Block&& b) {
if (this == &b)
return *this;
destroy();
info = b.info;
info->mover(*this, b.data());
return *this;
}

Block(Block const& b) = delete;
void operator=(Block const&) = delete;

template
void construct(D&& d) {
using D_Val = typename std::remove_reference::type;

Solution

Interesting.

You should add template emplace_back(Args&&...).

In terms of automatically determining blocksize, you can add a helper function like:

template 
std::size_t get_max_size() {
  return std::max({ sizeof(Args)... });
}


Users can then list the derived classes they want to use and use that to compute the block size.

Code Snippets

template <typename... Args>
std::size_t get_max_size() {
  return std::max({ sizeof(Args)... });
}

Context

StackExchange Code Review Q#19275, answer score: 2

Revisions (0)

No revisions yet.