Skip to content

Instantly share code, notes, and snippets.

@LusainKim
Created May 30, 2019 03:19
Show Gist options
  • Save LusainKim/6156e5008d86e1465e2df109ab6b28c9 to your computer and use it in GitHub Desktop.
Save LusainKim/6156e5008d86e1465e2df109ab6b28c9 to your computer and use it in GitHub Desktop.
Implemented a container wrapper class that type and value corresponded 1: 1, and all elements are base to Ty, used C++14 (working)
#include <memory>
#include <utility>
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
template<typename Ty, typename KeyTy = std::type_index, typename ValTy = std::unique_ptr<Ty>>
class reflection_manager
: private std::unordered_map<KeyTy, std::unique_ptr<Ty>>
{
public:
using base_type = Ty;
using key_type = KeyTy;
using value_type = ValTy;
using my_class = reflection_manager<base_type>;
using base_class = std::unordered_map<key_type, std::unique_ptr<base_type>>;
public:
using base_class::begin;
using base_class::end;
private:
using base_class::insert;
using base_class::erase;
using base_class::at;
public:
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
my_class& insert(std::unique_ptr<derived_type>&& value)
{
key_type keyval{ key<derived_type>() };
if (exist<derived_type>()) erase(keyval);
insert(std::make_pair(std::move(keyval), std::move(value)));
return *this;
}
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
bool erase()
{
key_type keyval{ key<derived_type>() };
if (!exist<derived_type>()) return false;
erase(keyval);
return true;
}
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
bool exist() const { return count(key<derived_type>()) > 0; }
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
derived_type* get()
{
key_type keyval{ key<derived_type>() };
if (!exist<derived_type>()) return nullptr;
return std::static_pointer_cast<derived_type*>(at(keyval).get());
}
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
const derived_type* get() const
{
key_type keyval{ key<derived_type>() };
if (!exist<derived_type>()) return nullptr;
return std::static_pointer_cast<derived_type*>(at(keyval).get());
}
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
operator derived_type*() { return get<derived_type>(); }
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
operator const derived_type*() const { return get<derived_type>(); }
private:
template<typename derived_type, std::enable_if_t<std::is_base_of_v<base_type, derived_type>, int> = 0>
key_type key() const { return std::type_index{ typeid(derived_type) }; }
};
struct Base { virtual const char* say() const = 0; };
struct A : Base { const char* say() const override { return "this structure is A"; } };
struct B : Base { const char* say() const override { return "this structure is B"; } };
struct C : Base { const char* say() const override { return "this structure is C"; } };
struct D { const char* say() const { return "this structure is D"; } };
#include <iostream>
int main()
{
reflection_manager<Base> m;
m.insert(std::make_unique<A>());
m.insert(std::make_unique<B>());
m.insert(std::make_unique<C>());
// error: C2664
// m.insert(std::make_unique<D>());
for (auto& p : m) std::cout << p.second->say() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment