#ifndef NALL_ANY_HPP #define NALL_ANY_HPP #include #include namespace nall { struct any { bool empty() const { return container; } void reset() { if(container) { delete container; container = nullptr; } } const std::type_info& type() const { return container ? container->type() : typeid(void); } template any& operator=(const T& value) { typedef typename type_if< std::is_array::value, typename std::remove_extent::type>::type*, T >::type auto_t; if(type() == typeid(auto_t)) { static_cast*>(container)->value = (auto_t)value; } else { if(container) delete container; container = new holder((auto_t)value); } return *this; } any& operator=(const any& source) { if(container) { delete container; container = nullptr; } if(source.container) container = source.container->copy(); return *this; } any& operator=(any&& source) { if(container) delete container; container = source.container; source.container = nullptr; return *this; } any() = default; any(const any& source) { operator=(source); } any(any&& source) { operator=(std::move(source)); } template any(const T& value) { operator=(value); } ~any() { reset(); } private: struct placeholder { virtual const std::type_info& type() const = 0; virtual placeholder* copy() const = 0; virtual ~placeholder() {} }; placeholder* container = nullptr; template struct holder : placeholder { T value; const std::type_info& type() const { return typeid(T); } placeholder* copy() const { return new holder(value); } holder(const T& value) : value(value) {} }; template friend T any_cast(any&); template friend T any_cast(const any&); template friend T* any_cast(any*); template friend const T* any_cast(const any*); }; template T any_cast(any& value) { typedef typename std::remove_reference::type nonref; if(value.type() != typeid(nonref)) throw; return static_cast*>(value.container)->value; } template T any_cast(const any& value) { typedef const typename std::remove_reference::type nonref; if(value.type() != typeid(nonref)) throw; return static_cast*>(value.container)->value; } template T* any_cast(any* value) { if(!value || value->type() != typeid(T)) return nullptr; return &static_cast*>(value->container)->value; } template const T* any_cast(const any* value) { if(!value || value->type() != typeid(T)) return nullptr; return &static_cast*>(value->container)->value; } } #endif