2014-01-09 22:01:29 +01:00
|
|
|
#ifndef value_hh_INCLUDED
|
|
|
|
#define value_hh_INCLUDED
|
|
|
|
|
2017-03-07 01:30:54 +01:00
|
|
|
#include "hash_map.hh"
|
2014-01-09 22:01:29 +01:00
|
|
|
#include "units.hh"
|
|
|
|
|
2015-06-25 20:41:53 +02:00
|
|
|
#include <type_traits>
|
2014-12-16 19:57:19 +01:00
|
|
|
#include <memory>
|
|
|
|
|
2014-01-09 22:01:29 +01:00
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
|
|
|
struct bad_value_cast {};
|
|
|
|
|
|
|
|
struct Value
|
|
|
|
{
|
|
|
|
Value() = default;
|
|
|
|
|
2015-06-25 20:41:53 +02:00
|
|
|
template<typename T,
|
|
|
|
typename = typename std::enable_if<not std::is_same<Value, T>::value>::type>
|
2016-03-06 02:35:32 +01:00
|
|
|
Value(T&& val)
|
|
|
|
: m_value{new Model<typename std::remove_reference<T>::type>{std::forward<T>(val)}} {}
|
2014-01-09 22:01:29 +01:00
|
|
|
|
2014-11-04 23:18:19 +01:00
|
|
|
Value(const Value& val) = delete;
|
2014-01-09 22:01:29 +01:00
|
|
|
Value(Value&&) = default;
|
|
|
|
|
2014-11-04 23:18:19 +01:00
|
|
|
Value& operator=(const Value& val) = delete;
|
2014-01-09 22:01:29 +01:00
|
|
|
Value& operator=(Value&& val) = default;
|
|
|
|
|
|
|
|
explicit operator bool() const { return (bool)m_value; }
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool is_a() const
|
|
|
|
{
|
|
|
|
return m_value and m_value->type() == typeid(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
T& as()
|
|
|
|
{
|
|
|
|
if (not is_a<T>())
|
|
|
|
throw bad_value_cast{};
|
|
|
|
return static_cast<Model<T>*>(m_value.get())->m_content;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
const T& as() const
|
|
|
|
{
|
|
|
|
return const_cast<Value*>(this)->as<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct Concept
|
|
|
|
{
|
2017-01-08 23:30:15 +01:00
|
|
|
virtual ~Concept() = default;
|
2014-01-09 22:01:29 +01:00
|
|
|
virtual const std::type_info& type() const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
2015-01-18 19:49:32 +01:00
|
|
|
struct Model : public Concept, public UseMemoryDomain<MemoryDomain::Values>
|
2014-01-09 22:01:29 +01:00
|
|
|
{
|
|
|
|
Model(T&& val) : m_content(std::move(val)) {}
|
|
|
|
const std::type_info& type() const override { return typeid(T); }
|
|
|
|
|
|
|
|
T m_content;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::unique_ptr<Concept> m_value;
|
|
|
|
};
|
|
|
|
|
2016-12-03 14:17:42 +01:00
|
|
|
enum class ValueId : int {};
|
2014-01-09 22:01:29 +01:00
|
|
|
|
2016-12-03 14:17:42 +01:00
|
|
|
inline ValueId get_free_value_id()
|
|
|
|
{
|
|
|
|
static int next = 0;
|
|
|
|
return (ValueId)(next++);
|
|
|
|
}
|
2014-01-09 22:01:29 +01:00
|
|
|
|
2017-03-07 01:30:54 +01:00
|
|
|
using ValueMap = HashMap<ValueId, Value, MemoryDomain::Values>;
|
2014-01-09 22:01:29 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // value_hh_INCLUDED
|