#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <functional>
#include <type_traits>
template <typename Type, bool Selector>
struct default_creator_impl;
template <typename Type, bool Selector>
struct default_deleter_impl;
// for non-POD types
template <typename Type>
struct default_creator_impl<Type, false>
{
Type* operator()()
{
Type* object = static_cast<Type*>(std::malloc(sizeof(Type)));
return new (object) Type;
}
};
template <typename Type>
struct default_deleter_impl<Type, false>
{
void operator()(void* object)
{
reinterpret_cast<Type*>(object)->Type::~Type();
free(object);
}
};
// for simple types
template <typename Type>
struct default_creator_impl<Type, true>
{
Type* operator()()
{
return static_cast<Type*>(std::malloc(sizeof(Type)));
}
};
template <typename Type>
struct default_deleter_impl<Type, true>
{
void operator()(void* object)
{
free(object);
}
};
template <typename Type>
using default_creator = default_creator_impl<Type, std::has_trivial_default_constructor<Type>::value>;
template <typename Type>
using default_deleter = default_deleter_impl<Type, std::has_trivial_default_constructor<Type>::value>;
class element_t
{
std::function<void(void*)> deleter;
void* memory;
public:
element_t() : memory(nullptr) { }
element_t(element_t&&) = default;
element_t(const element_t&) = delete;
~element_t() { if (deleter) deleter(memory); }
template <typename Type>
operator Type&()
{
if (memory == nullptr)
{
memory = default_creator<Type>()();
deleter = default_deleter<Type>();
}
return *reinterpret_cast<Type*>(memory);
}
};
class Foo
{
public:
using size_type = std::size_t;
private:
static size_type maximum_size;
std::vector<element_t> elements;
public:
Foo() = default;
template <typename Value>
Value& get()
{
static const auto index = []() -> size_type
{
auto current_index = maximum_size;
++maximum_size;
return current_index;
}();
if (elements.size() <= index)
{
elements.resize(index + 1);
}
return elements[index];
}
static size_type get_maximum_size()
{
return maximum_size;
}
size_type get_current_size() const
{
return elements.size();
}
};
Foo::size_type Foo::maximum_size = 0;
struct Haha
{
Haha() { std::cout << "create" << std::endl; }
~Haha() { std::cout << "destroy" << std::endl; }
};
int main()
{
{
Foo a;
a.get<Haha>();
}
}