#ifndef HEADER_BASE_CANY #define HEADER_BASE_CANY #include #include namespace base { class CAny { public: CAny() noexcept : _content(0) {} template CAny(const ValueType & value) : _content(new CHolder(value)) {} CAny(const CAny & other) : _content(other._content ? other._content->Clone() : 0) {} CAny(CAny&& other) noexcept : _content(other._content) { other._content = 0; } ~CAny() noexcept { delete _content; } public: // modifiers CAny& Swap(CAny & rhs) noexcept { std::swap(_content, rhs._content); return *this; } template CAny& operator=(const ValueType & rhs) { CAny(rhs).Swap(*this); return *this; } CAny& operator=(CAny rhs) { CAny(rhs).Swap(*this); return *this; } // move assignement CAny& operator=(CAny&& rhs) noexcept { rhs.Swap(*this); CAny().Swap(rhs); return *this; } public: // queries bool Empty() const noexcept { return !_content; } void Clear() noexcept { CAny().Swap(*this); } const std::type_info& Type() const noexcept { return _content ? _content->Type() : typeid(void); } class CPlaceHolder { public: virtual ~CPlaceHolder() { } // queries virtual const std::type_info& Type() const noexcept = 0; virtual CPlaceHolder * Clone() const = 0; }; template class CHolder : public CPlaceHolder { public: CHolder(const ValueType& value) : _held(value) { } CHolder(ValueType&& value) : _held(static_cast(value)) { } // queries virtual const std::type_info& Type() const noexcept { return typeid(ValueType); } virtual CPlaceHolder * Clone() const { return new CHolder(_held); } public: ValueType _held; private: CHolder & operator=(const CHolder&) {} }; private: // representation template friend ValueType* any_cast(CAny *) noexcept; CPlaceHolder* _content; }; class bad_any_cast: public std::exception { public: virtual const char * what() const noexcept { return "bad_any_cast : failed conversion using any_cast"; } }; template ValueType* any_cast(CAny * operand) noexcept { if (operand && operand->Type() == typeid(ValueType)) { return &static_cast *>(operand->_content)->_held; } return nullptr; } template const ValueType * any_cast(const CAny * operand) noexcept { return any_cast(const_cast(operand)); } template ValueType any_cast(CAny & operand) { ValueType * result = any_cast(&operand); if (!result) std::exception(bad_any_cast()); return static_cast(*result); } template inline ValueType any_cast(const CAny& operand) { return any_cast(const_cast(operand)); } template inline ValueType any_cast(CAny&& operand) { return any_cast(operand); } } #endif