Lunchbox
1.6.0
|
00001 00002 /* Copyright (c) 2012, Daniel Nachbaur <daniel.nachbaur@gmail.com> 00003 * 00004 * This library is free software; you can redistribute it and/or modify it under 00005 * the terms of the GNU Lesser General Public License version 3.0 as published 00006 * by the Free Software Foundation. 00007 * 00008 * This library is distributed in the hope that it will be useful, but WITHOUT 00009 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00010 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00011 * details. 00012 * 00013 * You should have received a copy of the GNU Lesser General Public License 00014 * along with this library; if not, write to the Free Software Foundation, Inc., 00015 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00016 */ 00017 00018 // Based on boost/any.hpp 00019 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. 00020 // 00021 // Distributed under the Boost Software License, Version 1.0. (See 00022 // accompanying file LICENSE_1_0.txt or copy at 00023 // http://www.boost.org/LICENSE_1_0.txt) 00024 00025 00026 #ifndef LUNCHBOX_ANY_H 00027 #define LUNCHBOX_ANY_H 00028 00029 #include <lunchbox/api.h> 00030 #include <lunchbox/debug.h> 00031 00032 #include <boost/type_traits/remove_reference.hpp> 00033 #include <boost/shared_ptr.hpp> 00034 #include <boost/serialization/access.hpp> 00035 #include <boost/serialization/assume_abstract.hpp> 00036 #include <boost/serialization/base_object.hpp> 00037 #include <boost/serialization/shared_ptr.hpp> 00038 00039 // See boost/python/type_id.hpp 00040 // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp 00041 # if (defined(__GNUC__) && __GNUC__ >= 3) \ 00042 || defined(_AIX) \ 00043 || ( defined(__sgi) && defined(__host_mips)) \ 00044 || (defined(__hpux) && defined(__HP_aCC)) \ 00045 || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) 00046 # define BOOST_AUX_ANY_TYPE_ID_NAME 00047 # include <cstring> 00048 # endif 00049 00050 00051 namespace lunchbox 00052 { 00053 00061 class Any 00062 { 00063 public: 00067 LUNCHBOX_API Any(); 00068 00070 template< typename ValueType > 00071 Any( const ValueType& value ) 00072 : content( new holder< ValueType >( value )) 00073 { 00074 } 00075 00077 LUNCHBOX_API Any( const Any& other ); 00078 00080 LUNCHBOX_API ~Any(); 00082 00086 LUNCHBOX_API Any& swap( Any& rhs ); 00087 00089 template< typename ValueType > 00090 Any& operator=( const ValueType& rhs ) 00091 { 00092 Any( rhs ).swap( *this ); 00093 return *this; 00094 } 00095 00097 LUNCHBOX_API Any& operator=( Any rhs ); 00099 00103 LUNCHBOX_API bool empty() const; 00104 00110 LUNCHBOX_API const std::type_info& type() const; 00111 00116 LUNCHBOX_API bool operator == ( const Any& rhs ) const; 00117 00122 bool operator != ( const Any& rhs ) const { return !(*this == rhs); } 00124 00125 00127 class placeholder 00128 { 00129 public: 00130 virtual ~placeholder() {} 00131 00132 virtual bool operator == ( const placeholder& rhs ) const = 0; 00133 00134 bool operator != ( const placeholder& rhs ) const 00135 { return !(*this == rhs); } 00136 00137 virtual const std::type_info& type() const = 0; 00138 00139 virtual placeholder* clone() const = 0; 00140 00141 private: 00142 friend class boost::serialization::access; 00143 template< class Archive > 00144 void serialize( Archive & ar, const unsigned int version ) 00145 { 00146 } 00147 }; 00148 00149 BOOST_SERIALIZATION_ASSUME_ABSTRACT(placeholder) 00150 00151 00152 template< typename ValueType > 00153 class holder : public placeholder 00154 { 00155 public: 00156 holder() 00157 : held() 00158 { 00159 } 00160 00161 holder( const ValueType& value ) 00162 : held( value ) 00163 { 00164 } 00165 00166 virtual const std::type_info& type() const 00167 { 00168 return typeid(ValueType); 00169 } 00170 00171 virtual bool operator == ( const placeholder& rhs ) const 00172 { 00173 return held == static_cast< const holder& >( rhs ).held; 00174 } 00175 00176 virtual placeholder* clone() const 00177 { 00178 return new holder( held ); 00179 } 00180 00181 ValueType held; 00182 00183 private: 00184 holder& operator=( const holder& ); 00185 00186 friend class boost::serialization::access; 00187 template< class Archive > 00188 void serialize( Archive & ar, const unsigned int version ) 00189 { 00190 // serialize base class information 00191 ar & boost::serialization::base_object< placeholder >( *this ); 00192 ar & held; 00193 } 00194 }; 00195 00196 private: 00197 template< typename ValueType > 00198 friend ValueType* any_cast( Any* ); 00199 00200 template< typename ValueType > 00201 friend ValueType* unsafe_any_cast( Any* ); 00202 00203 friend class boost::serialization::access; 00204 template< class Archive > 00205 void serialize( Archive & ar, const unsigned int version ) 00206 { 00207 ar & content; 00208 } 00209 00210 boost::shared_ptr< placeholder > content; 00211 }; 00212 00214 class bad_any_cast : public std::bad_cast 00215 { 00216 public: 00217 LUNCHBOX_API bad_any_cast( const std::string& from, const std::string& to ); 00218 00219 virtual const char* what() const throw() { return data; } 00220 00221 private: 00222 char data[256]; 00223 }; 00224 00231 template< typename ValueType > 00232 ValueType* any_cast( Any* operand ) 00233 { 00234 return operand && 00235 #ifdef BOOST_AUX_ANY_TYPE_ID_NAME 00236 std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0 00237 #else 00238 operand->type() == typeid(ValueType) 00239 #endif 00240 ? &static_cast<Any::holder<ValueType> *>(operand->content.get())->held 00241 : 0; 00242 } 00243 00250 template< typename ValueType > 00251 inline const ValueType* any_cast( const Any* operand ) 00252 { 00253 return any_cast<ValueType>(const_cast<Any *>(operand)); 00254 } 00255 00263 template< typename ValueType > 00264 ValueType any_cast( Any& operand ) 00265 { 00266 typedef typename boost::remove_reference< ValueType >::type nonref; 00267 00268 nonref* result = any_cast< nonref >( &operand ); 00269 if( !result ) 00270 boost::throw_exception( 00271 bad_any_cast( demangleTypeID( operand.type().name( )), 00272 demangleTypeID( typeid( nonref ).name( )))); 00273 return *result; 00274 } 00275 00283 template< typename ValueType > 00284 inline ValueType any_cast( const Any& operand ) 00285 { 00286 typedef typename boost::remove_reference< ValueType >::type nonref; 00287 00288 return any_cast< const nonref& >( const_cast< Any& >( operand )); 00289 } 00290 00297 template< typename ValueType > 00298 inline ValueType* unsafe_any_cast( Any* operand ) 00299 { 00300 return &static_cast< Any::holder< ValueType >* >( 00301 operand->content.get( ))->held; 00302 } 00303 00310 template< typename ValueType > 00311 inline const ValueType* unsafe_any_cast( const Any* operand ) 00312 { 00313 return unsafe_any_cast< ValueType >( const_cast< Any* > ( operand )); 00314 } 00315 00322 template< typename ValueType > 00323 ValueType unsafe_any_cast( Any& operand ) 00324 { 00325 typedef typename boost::remove_reference< ValueType >::type nonref; 00326 return *unsafe_any_cast< nonref >( &operand ); 00327 } 00328 00335 template< typename ValueType > 00336 ValueType unsafe_any_cast( const Any& operand ) 00337 { 00338 typedef typename boost::remove_reference< ValueType >::type nonref; 00339 return unsafe_any_cast< const nonref& >( const_cast< Any& >( operand )); 00340 } 00341 00342 } 00343 00344 #endif