Created
November 11, 2018 19:22
-
-
Save bluebear94/0b1cbd85a09b2dc62d8ce2b3545f05e2 to your computer and use it in GitHub Desktop.
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
#pragma once | |
#include <any> | |
#include <optional> | |
#include <typeindex> | |
#include <typeinfo> | |
#include <unordered_map> | |
namespace agl { | |
/// A template type function that returns the argument. | |
/// This is identitcal to std::type_identity_t from C++20. | |
template<typename A> using TypeIdentity = A; | |
/** | |
* \brief A class that maps types to instances to those types. | |
* | |
* \tparam F A template type function that should be applied to the map | |
* values. | |
*/ | |
template<template<typename A> typename F = TypeIdentity> class AnyMap { | |
public: | |
std::optional<std::reference_wrapper<std::any>> get(std::type_index k) { | |
auto it = underlying.find(k); | |
if (it == underlying.end()) return std::nullopt; | |
return std::ref(it->second); | |
} | |
std::optional<std::reference_wrapper<const std::any>> get(std::type_index k) const { | |
auto it = underlying.find(k); | |
if (it == underlying.end()) return std::nullopt; | |
return std::cref(it->second); | |
} | |
template<typename T> std::optional<std::reference_wrapper<F<T>>> get() { | |
auto it = underlying.find(typeid(T)); | |
if (it == underlying.end()) return std::nullopt; | |
return std::any_cast<F<T>&>(it->second); | |
} | |
template<typename T> std::optional<std::reference_wrapper<const F<T>>> get() const { | |
auto it = underlying.find(typeid(T)); | |
if (it == underlying.end()) return std::nullopt; | |
return std::any_cast<const F<T>&>(it->second); | |
} | |
template<typename T, typename... A> F<T>& emplace(A&&... args) { | |
std::any& target = underlying[typeid(T)]; | |
return target.emplace<F<T>>(std::forward<A>(args)...); | |
} | |
template<typename T, typename... A> void erase() { | |
underlying.erase(typeid(T)); | |
} | |
private: | |
std::unordered_map<std::type_index, std::any> underlying; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment