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 #if !defined(BOOST_PP_IS_ITERATING) 12 13 #ifndef BOOST_TYPE_ERASURE_CONSTRUCTIBLE_HPP_INCLUDED 14 #define BOOST_TYPE_ERASURE_CONSTRUCTIBLE_HPP_INCLUDED 15 16 #include <boost/detail/workaround.hpp> 17 #include <boost/preprocessor/iteration/iterate.hpp> 18 #include <boost/preprocessor/repetition/enum_params.hpp> 19 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 20 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 21 #include <boost/type_erasure/detail/storage.hpp> 22 #include <boost/type_erasure/call.hpp> 23 #include <boost/type_erasure/concept_interface.hpp> 24 #include <boost/type_erasure/config.hpp> 25 #include <boost/type_erasure/param.hpp> 26 27 namespace boost { 28 namespace type_erasure { 29 30 template<class Sig> 31 struct constructible; 32 33 namespace detail { 34 35 template<class Sig> 36 struct null_construct; 37 38 template<class C> 39 struct get_null_vtable_entry; 40 41 template<class C, class Sig> 42 struct vtable_adapter; 43 44 } 45 46 #ifdef BOOST_TYPE_ERASURE_DOXYGEN 47 48 /** 49 * The @ref constructible concept enables calling the 50 * constructor of a type contained by an @ref any. 51 * @c Sig should be a function signature. The return 52 * type is the placeholder specifying the type to 53 * be constructed. The arguments are the argument 54 * types of the constructor. The arguments of 55 * @c Sig may be placeholders. 56 * 57 * \note @ref constructible may not be specialized and 58 * may not be passed to \call as it depends on the 59 * implementation details of @ref any. 60 */ 61 template<class Sig> 62 struct constructible {}; 63 64 #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ 65 !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ 66 !BOOST_WORKAROUND(BOOST_MSVC, == 1800) 67 68 template<class R, class... T> 69 struct constructible<R(T...)> 70 { 71 static ::boost::type_erasure::detail::storage applyboost::type_erasure::constructible72 apply(T... arg) 73 { 74 ::boost::type_erasure::detail::storage result; 75 result.data = new R(::std::forward<T>(arg)...); 76 return result; 77 } 78 }; 79 80 /// INTERNAL ONLY 81 template<class Base, class Tag, class... T> 82 struct concept_interface< 83 ::boost::type_erasure::constructible<Tag(T...)>, 84 Base, 85 Tag 86 > : Base 87 { 88 using Base::_boost_type_erasure_deduce_constructor; 89 ::boost::type_erasure::constructible<Tag(T...)>* _boost_type_erasure_deduce_constructorboost::type_erasure::concept_interface90 _boost_type_erasure_deduce_constructor( 91 typename ::boost::type_erasure::as_param<Base, T>::type...) const 92 { 93 return 0; 94 } 95 }; 96 97 namespace detail { 98 99 template<class... T> 100 struct null_construct<void(T...)> 101 { 102 static ::boost::type_erasure::detail::storage valueboost::type_erasure::detail::null_construct103 value(T...) 104 { 105 ::boost::type_erasure::detail::storage result; 106 result.data = 0; 107 return result; 108 } 109 }; 110 111 template<class T, class R, class... U> 112 struct get_null_vtable_entry<vtable_adapter<constructible<T(const T&)>, R(U...)> > 113 { 114 typedef null_construct<void(U...)> type; 115 }; 116 117 } 118 119 #else 120 121 #define BOOST_PP_FILENAME_1 <boost/type_erasure/constructible.hpp> 122 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) 123 #include BOOST_PP_ITERATE() 124 125 #endif 126 127 } 128 } 129 130 #endif 131 132 #else 133 134 #define N BOOST_PP_ITERATION() 135 136 #define BOOST_TYPE_ERASURE_ARG_DECL(z, n, data) \ 137 typename ::boost::type_erasure::as_param< \ 138 Base, \ 139 BOOST_PP_CAT(T, n) \ 140 >::type 141 142 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 143 #define BOOST_TYPE_ERASURE_FORWARD_I(z, n, data) ::std::forward<BOOST_PP_CAT(T, n)>(BOOST_PP_CAT(arg, n)) 144 #define BOOST_TYPE_ERASURE_FORWARD(n) BOOST_PP_ENUM(n, BOOST_TYPE_ERASURE_FORWARD_I, ~) 145 #else 146 #define BOOST_TYPE_ERASURE_FORWARD(n) BOOST_PP_ENUM_PARAMS(n, arg) 147 #endif 148 149 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> 150 struct constructible<R(BOOST_PP_ENUM_PARAMS(N, T))> 151 { 152 static ::boost::type_erasure::detail::storage applyconstructible153 apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, arg)) 154 { 155 ::boost::type_erasure::detail::storage result; 156 result.data = new R(BOOST_TYPE_ERASURE_FORWARD(N)); 157 return result; 158 } 159 }; 160 161 template<class Base BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class Tag> 162 struct concept_interface< 163 ::boost::type_erasure::constructible<Tag(BOOST_PP_ENUM_PARAMS(N, T))>, 164 Base, 165 Tag 166 > : Base 167 { 168 using Base::_boost_type_erasure_deduce_constructor; 169 ::boost::type_erasure::constructible<Tag(BOOST_PP_ENUM_PARAMS(N, T))>* 170 _boost_type_erasure_deduce_constructor( 171 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_ARG_DECL, ~)) const 172 { 173 return 0; 174 } 175 }; 176 177 namespace detail { 178 179 template<BOOST_PP_ENUM_PARAMS(N, class T)> 180 struct null_construct<void(BOOST_PP_ENUM_PARAMS(N, T))> 181 { 182 static ::boost::type_erasure::detail::storage valuedetail::null_construct183 value(BOOST_PP_ENUM_PARAMS(N, T)) 184 { 185 ::boost::type_erasure::detail::storage result; 186 result.data = 0; 187 return result; 188 } 189 }; 190 191 template<class T, class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> 192 struct get_null_vtable_entry<vtable_adapter<constructible<T(const T&)>, R(BOOST_PP_ENUM_PARAMS(N, T))> > 193 { 194 typedef null_construct<void(BOOST_PP_ENUM_PARAMS(N, T))> type; 195 }; 196 197 } 198 199 #undef BOOST_TYPE_ERASURE_FORWARD 200 #undef BOOST_TYPE_ERASURE_FORWARD_I 201 202 #undef BOOST_TYPE_ERASURE_ARG_DECL 203 #undef N 204 205 #endif 206