// Copyright (C) 2014-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. /** * @file any.hh * @author Kornel Kisielewicz * @brief any type * * based on http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf */ #ifndef NV_STL_ANY_HH #define NV_STL_ANY_HH #include #include #include #include #error "any type is currently unsupported!" namespace nv { class any { public: any() : m_content( nullptr ) {} any( const any& other ) : m_content( other.m_content ? other.m_content->clone() : nullptr ) {} template< typename T > any( const T& value ) : m_content( new holder( value ) ) {} any( any&& other ) : m_content( other.m_content ) {} template< typename T > any( T&& value ) : m_content( new holder( forward(value) ) ) {} ~any() { delete m_content; } any& swap( any& rhs ) { nv::swap( m_content, rhs.m_content ); return *this; } any& operator=( const any& rhs ) { return swap( any( rhs ) ); } any& operator=( any&& rhs ) { swap( rhs ); any().swap( rhs ); return *this; } template < typename T > any& operator= ( T&& rhs ) { any( forward(rhs) ).swap(*this); return *this; } operator const void* () const { return m_content; } template< typename T > bool copy_to( T& value ) const { const T* copyable = to_ptr(); if ( copyable ) value = *copyable; return copyable; } template< typename T > const T* to_ptr() const { return type_info() == typeid(T) ? &static_cast< holder *>(m_content)->held : nullptr; } bool empty() const { return !m_content; } void clear() { any().swap(*this); } const std::type_info &type_info() const { return m_content ? m_content->type_info() : typeid(void); } private: class placeholder { public: virtual const std::type_info& type_info() const = 0; virtual placeholder *clone() const = 0; virtual ~placeholder() {} }; template< typename T > class holder : public placeholder { public: holder( const T& value ) : held(value) { } holder( T&& value ) : held(forward(value)) { } virtual const std::type_info &type_info() const { return typeid(T); } virtual placeholder *clone() const { return new holder(held); } const T held; }; placeholder *m_content; }; inline void swap( any& lhs, any& rhs ) { lhs.swap(rhs); } template< typename T > T any_cast( const any& operand ) { const T* result = operand.to_ptr(); return result ? *result : throw std::bad_cast(); } } #endif // NV_STL_ANY_HH