#ifndef NALL_ANY_HPP #define NALL_ANY_HPP #include #include namespace nall { struct any { bool empty() const { return container; } 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() : container(nullptr) {} ~any() { if(container) delete container; } template any(const T& value_) : container(nullptr) { operator=(value_); } private: struct placeholder { virtual const std::type_info& type() const = 0; } *container; template struct holder : placeholder { T value; const std::type_info& type() const { return typeid(T); } 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