异构容器实现:
#include <vector>
#include <unordered_map>
#include <functional>
#include <iostream>
#include<experimental/type_traits>
// ### heterogeneous container ###
namespace container
{
template<class...>
struct type_list{};
template<class... TYPES>
struct visitor_base
{
using types = container::type_list<TYPES...>;
};
struct entity_container
{
public:
entity_container() = default;
template<typename ...Ts>
entity_container(Ts ...args)
{
auto loop = [&](auto& arg)
{
this->push_back(arg);
};
(loop(args), ...);
}
entity_container(const entity_container& _other)
{
*this = _other;
}
entity_container& operator=(const entity_container& _other)
{
clear();
clear_functions = _other.clear_functions;
copy_functions = _other.copy_functions;
size_functions = _other.size_functions;
stored_ids_functions = _other.stored_ids_functions;
id_delete_functions = _other.id_delete_functions;
for (auto&& copy_function : copy_functions)
{
copy_function(_other, *this);
}
return *this;
}
template<class T>
void push_back(const T& _t)
{
//is a new container being made? if so ...
if (items<T>.find(this) == std::end(items<T>))
{
clear_functions.emplace_back([](entity_container& _c){items<T>.erase(&_c);});
id_delete_functions.emplace_back([&](entity_container& _c, int id)
{
for(auto& ent : items<T>[&_c])
{
if(ent.getId() == id)
items<T>[&_c].erase( std::find(items<T>[&_c].begin(), items<T>[&_c].end(), ent) );
}
});
copy_functions.emplace_back([](const entity_container& _from, entity_container& _to)
{
items<T>[&_to] = items<T>[&_from];
});
size_functions.emplace_back([](const entity_container& _c){return items<T>[&_c].size();}); //returns the size of the vector
stored_ids_functions.emplace_back([](const entity_container& _c)
{
std::vector<int> stored_ids;
for(auto& ent : items<T>[&_c])
stored_ids.push_back(ent.getId());
return stored_ids;
});
}
items<T>[this].push_back(_t);
}
void clear()
{
for (auto&& clear_func : clear_functions)
{
clear_func(*this);
}
}
template<class T>
size_t number_of() const
{
auto iter = items<T>.find(this);
if (iter != items<T>.cend())
return items<T>[this].size();
return 0;
}
size_t size() const
{
size_t sum = 0;
for (auto&& size_func : size_functions)
sum += size_func(*this);
// gotta be careful about this overflowing
return sum;
}
bool exists_by_id(int id) const
{
for(auto&& id_func : stored_ids_functions) //visit each of the id functions
{
std::vector<int> ids = id_func(*this);
auto res = std::find(std::begin(ids), std::end(ids), id);
if(res != std::end(ids))
return true;
}
return false;
}
void delete_by_id(int id)
{
for(auto&& id_delete_func : id_delete_functions)
id_delete_func(*this, id);
}
void print_stored_ids()
{
for(auto&& id_func : stored_ids_functions) //visit each of the id functions
{
std::vector<int> ids = id_func(*this);
for(auto& id : ids)
std::cout << "id: " << id << std::endl;
}
}
~entity_container()
{
clear();
}
template<class T>
void visit(T&& visitor)
{
visit_impl(visitor, typename std::decay_t<T>::types{});
}
private:
template<class T>
static std::unordered_map<const entity_container*, std::vector<T>> items;
template<class T, class U>
using visit_function = decltype(std::declval<T>().operator()(std::declval<U&>()));
template<class T, class U>
static constexpr bool has_visit_v = std::experimental::is_detected<visit_function, T, U>::value;
template<class T, template<class...> class TLIST, class... TYPES>
void visit_impl(T&& visitor, TLIST<TYPES...>)
{
(..., visit_impl_help<std::decay_t<T>, TYPES>(visitor));
}
template<class T, class U>
void visit_impl_help(T& visitor)
{
static_assert(has_visit_v<T, U>, "Visitors must provide a visit function accepting a reference for each type");
for (auto&& element : items<U>[this])
{
visitor(element);
}
}
std::vector<std::function<void(entity_container&)>> clear_functions;
std::vector<std::function<void(const entity_container&, entity_container&)>> copy_functions;
std::vector<std::function<size_t(const entity_container&)>> size_functions;
std::vector<std::function<std::vector<int>(const entity_container&)>> stored_ids_functions;
std::vector<std::function<void(entity_container&, int)>> id_delete_functions;
};
template<class T>
std::unordered_map<const entity_container*, std::vector<T>> entity_container::items;
}
用途:
template<class T>
struct Entity
{
public:
Entity(int Id) : id(Id)
{
data = new T();
}
bool operator==(const Entity<T>& rhs) const {
return (this->id == rhs.id && this->data == rhs.data);
}
int getId(){return id;}
T*& getData(){ return data; }
private:
int id;
T* data;
};
struct A{};
struct B{};
struct C{};
/* ## main ## */
int main()
{
Entity<A> entity_a(1);
Entity<B> entity_b(2);
Entity<C> entity_c(3);
Entity<C> entity_d(10);
container::entity_container c(entity_a, entity_b, entity_c);
c.push_back(entity_d);
c.print_stored_ids(); //prints the id's of all store entities
c.delete_by_id(3); //deletes the store entities with the parsed id
c.delete_by_id(1);
c.delete_by_id(10);
c.print_stored_ids();
}
大部分来自https://gieseanw.wordpress.com/2017/05/03/a-true-heterogeneous-container-in-c/,并添加了一些个人添加以适应类型的容器,例如Entity(即带有ID和指向某些数据的指针)。可能对某人有用。