1 // Boost.TypeErasure library 2 // 3 // Copyright 2011 Steven Watanabe 4 // 5 // Distributed under the Boost Software License Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // $Id$ 10 11 #ifndef BOOST_TYPE_ERASURE_BUILTIN_HPP_INCLUDED 12 #define BOOST_TYPE_ERASURE_BUILTIN_HPP_INCLUDED 13 14 #include <boost/mpl/vector.hpp> 15 #include <boost/utility/enable_if.hpp> 16 #include <boost/type_traits/is_reference.hpp> 17 #include <boost/type_erasure/detail/storage.hpp> 18 #include <boost/type_erasure/placeholder.hpp> 19 #include <boost/type_erasure/constructible.hpp> 20 #include <boost/type_erasure/rebind_any.hpp> 21 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 22 # include <utility> // std::move 23 #endif 24 #include <typeinfo> 25 26 namespace boost { 27 namespace type_erasure { 28 29 /** 30 * The @ref destructible concept enables forwarding to 31 * the destructor of the contained type. This is required 32 * whenever an @ref any is created by value. 33 * 34 * \note The @ref destructible concept rarely needs to 35 * be specified explicitly, because it is included in 36 * the @ref copy_constructible concept. 37 * 38 * \note @ref destructible may not be specialized and 39 * may not be passed to \call as it depends on the 40 * implementation details of @ref any. 41 */ 42 template<class T = _self> 43 struct destructible 44 { 45 /** INTERNAL ONLY */ 46 typedef void (*type)(detail::storage&); 47 /** INTERNAL ONLY */ valueboost::type_erasure::destructible48 static void value(detail::storage& arg) 49 { 50 delete static_cast<T*>(arg.data); 51 } 52 /** INTERNAL ONLY */ applyboost::type_erasure::destructible53 static void apply(detail::storage& arg) 54 { 55 delete static_cast<T*>(arg.data); 56 } 57 }; 58 59 /** 60 * The @ref copy_constructible concept allows objects to 61 * be copied and destroyed. 62 * 63 * \note This concept is defined to match C++ 2003, 64 * [lib.copyconstructible]. It is not equivalent to 65 * the concept of the same name in C++11. 66 */ 67 template<class T = _self> 68 struct copy_constructible : 69 ::boost::mpl::vector<constructible<T(const T&)>, destructible<T> > 70 {}; 71 72 #ifdef BOOST_TYPE_ERASURE_DOXYGEN 73 74 /** 75 * Enables assignment of @ref any types. 76 */ 77 template<class T = _self, class U = const T&> 78 struct assignable 79 { 80 static void apply(T& dst, U src); 81 }; 82 83 #else 84 85 /** 86 * Enables assignment of @ref any types. 87 */ 88 template<class T = _self, class U = const T&> 89 struct assignable : 90 ::boost::mpl::vector<assignable<T, const U&> > 91 {}; 92 93 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 94 95 /** INTERNAL ONLY */ 96 template<class T, class U> 97 struct assignable<T, U&&> 98 { applyboost::type_erasure::assignable99 static void apply(T& dst, U&& src) { dst = std::forward<U>(src); } 100 }; 101 102 #endif 103 104 /** INTERNAL ONLY */ 105 template<class T, class U> 106 struct assignable<T, U&> 107 { applyboost::type_erasure::assignable108 static void apply(T& dst, U& src) { dst = src; } 109 }; 110 111 /** INTERNAL ONLY */ 112 template<class T, class U, class Base> 113 struct concept_interface<assignable<T, U>, Base, T, 114 typename ::boost::enable_if_c< ::boost::is_reference<U>::value>::type> : Base 115 { 116 using Base::_boost_type_erasure_deduce_assign; _boost_type_erasure_deduce_assignboost::type_erasure::concept_interface117 assignable<T, U>* _boost_type_erasure_deduce_assign( 118 typename ::boost::type_erasure::as_param<Base, U>::type) 119 { 120 return 0; 121 } 122 }; 123 124 #endif 125 126 /** 127 * Enables runtime type information. This is required 128 * if you want to use \any_cast or \typeid_of. 129 * 130 * \note @ref typeid_ cannot be specialized because several 131 * library components including \any_cast would not work 132 * correctly if its behavior changed. There is no need 133 * to specialize it anyway, since it works for all types. 134 * @ref typeid_ also cannot be passed to \call. To access it, 135 * use \typeid_of. 136 */ 137 template<class T = _self> 138 struct typeid_ 139 { 140 /** INTERNAL ONLY */ 141 typedef const std::type_info& (*type)(); 142 /** INTERNAL ONLY */ valueboost::type_erasure::typeid_143 static const std::type_info& value() 144 { 145 return typeid(T); 146 } 147 /** INTERNAL ONLY */ applyboost::type_erasure::typeid_148 static const std::type_info& apply() 149 { 150 return typeid(T); 151 } 152 }; 153 154 namespace detail { 155 156 template<class C> 157 struct get_null_vtable_entry; 158 159 template<class T> 160 struct get_null_vtable_entry< ::boost::type_erasure::typeid_<T> > 161 { 162 typedef typeid_<void> type; 163 }; 164 165 struct null_destroy { valueboost::type_erasure::detail::null_destroy166 static void value(::boost::type_erasure::detail::storage&) {} 167 }; 168 169 template<class T> 170 struct get_null_vtable_entry< ::boost::type_erasure::destructible<T> > 171 { 172 typedef ::boost::type_erasure::detail::null_destroy type; 173 }; 174 175 } 176 177 } 178 } 179 180 #endif 181