Skip to content

Instantly share code, notes, and snippets.

@bluebear94
Created November 11, 2018 19:22
Show Gist options
  • Save bluebear94/0b1cbd85a09b2dc62d8ce2b3545f05e2 to your computer and use it in GitHub Desktop.
Save bluebear94/0b1cbd85a09b2dc62d8ce2b3545f05e2 to your computer and use it in GitHub Desktop.
#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