Created
May 30, 2019 03:19
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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