#ifndef value_hh_INCLUDED #define value_hh_INCLUDED #include "hash_map.hh" #include "units.hh" #include #include namespace Kakoune { struct bad_value_cast {}; struct Value { Value() = default; template::value>> Value(T&& val) : m_value{new Model>{std::forward(val)}} {} Value(const Value& val) = delete; Value(Value&&) = default; Value& operator=(const Value& val) = delete; Value& operator=(Value&& val) = default; explicit operator bool() const { return (bool)m_value; } template bool is_a() const { return m_value and m_value->type() == typeid(T); } template T& as() { if (not is_a()) throw bad_value_cast{}; return static_cast*>(m_value.get())->m_content; } template const T& as() const { return const_cast(this)->as(); } private: struct Concept { virtual ~Concept() = default; virtual const std::type_info& type() const = 0; }; template struct Model : public Concept, public UseMemoryDomain { Model(T&& val) : m_content(std::move(val)) {} const std::type_info& type() const override { return typeid(T); } T m_content; }; std::unique_ptr m_value; }; enum class ValueId : int {}; inline ValueId get_free_value_id() { static int next = 0; return (ValueId)(next++); } using ValueMap = HashMap; } #endif // value_hh_INCLUDED