#include <type_traits>
#include <typeinfo>
#include "meta.h"
+#include "mspcore_api.h"
namespace Msp {
-class type_mismatch: public std::runtime_error
+class MSPCORE_API type_mismatch: public std::runtime_error
{
public:
type_mismatch(const std::type_info &, const std::type_info &);
};
-class Variant
+class MSPCORE_API Variant
{
public:
static constexpr unsigned INTERNAL_SIZE = 2*sizeof(void *);
template<typename T>
Variant(const T &v) { assign(v); }
Variant(const Variant &v) { copy_from(v); }
- ~Variant() { if(funcs) funcs->destroy(storage); }
+ ~Variant() { clear(); }
template<typename T>
Variant &operator=(const T &v) { assign(v); return *this; }
Variant &operator=(const Variant &v) { if(&v!=this) copy_from(v); return *this; }
+ void clear();
+
private:
template<typename T>
void assign(const T &);
const T &value() const { return const_cast<Variant *>(this)->get<T>(); }
template<typename T>
- bool has_type() const { return funcs==get_functions<typename std::remove_cv<T>::type>(); }
+ bool has_type() const { return type_equals(funcs, get_functions<typename std::remove_cv<T>::type>()); }
- bool has_same_type(const Variant &v) const { return (funcs && funcs==v.funcs); }
+ bool has_same_type(const Variant &v) const { return type_equals(funcs, v.funcs); }
template<typename T>
DEPRECATED bool check_type() const { return has_type<T>(); }
operator T() const { return value<T>(); }
private:
+ static bool type_equals(const Functions *, const Functions *);
+
template<typename T>
static constexpr bool is_small() { return (sizeof(T)<=INTERNAL_SIZE && alignof(T)<=alignof(void *)); }
};
-template<typename T>
-inline void Variant::assign(const T &value)
+inline void Variant::clear()
{
if(funcs)
funcs->destroy(storage);
+ funcs = nullptr;
+}
+template<typename T>
+inline void Variant::assign(const T &v)
+{
+ clear();
funcs = get_functions<typename std::remove_cv<T>::type>();
- create(storage, value);
+ create(storage, v);
}
inline void Variant::copy_from(const Variant &v)
{
- if(funcs)
- funcs->destroy(storage);
-
- funcs = v.funcs;
- if(funcs)
+ clear();
+ if((funcs = v.funcs))
funcs->clone(storage, v.storage);
}
return **reinterpret_cast<T **>(storage);
}
+inline bool Variant::type_equals(const Functions *funcs1, const Functions *funcs2)
+{
+ if(!funcs1 || !funcs2)
+ return false;
+ else if(funcs1==funcs2)
+ return true;
+ else
+ return funcs1->get_type()==funcs2->get_type();
+}
+
template<typename T>
inline const Variant::Functions *Variant::get_functions()
{