1 2 // (C) Copyright Edward Diener 2011,2012,2013 3 // Use, modification and distribution are subject to the Boost Software License, 4 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt). 6 7 #if !defined(BOOST_TTI_DETAIL_TEMPLATE_PARAMS_HPP) 8 #define BOOST_TTI_DETAIL_TEMPLATE_PARAMS_HPP 9 10 #include <boost/config.hpp> 11 #include <boost/mpl/bool.hpp> 12 #include <boost/mpl/eval_if.hpp> 13 #include <boost/mpl/has_xxx.hpp> 14 #include <boost/preprocessor/arithmetic/add.hpp> 15 #include <boost/preprocessor/arithmetic/sub.hpp> 16 #include <boost/preprocessor/array/elem.hpp> 17 #include <boost/preprocessor/cat.hpp> 18 #include <boost/preprocessor/punctuation/comma_if.hpp> 19 #include <boost/preprocessor/repetition/repeat.hpp> 20 #include <boost/preprocessor/repetition/enum.hpp> 21 #include <boost/preprocessor/array/enum.hpp> 22 #include <boost/preprocessor/array/size.hpp> 23 #include <boost/type_traits/is_class.hpp> 24 25 #if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) 26 27 #define BOOST_TTI_DETAIL_TEMPLATE_PARAMETERS(z,n,args) \ 28 BOOST_PP_ARRAY_ELEM(BOOST_PP_ADD(4,n),args) \ 29 /**/ 30 31 #define BOOST_TTI_DETAIL_HAS_MEMBER_IMPLEMENTATION(args,introspect_macro) \ 32 template \ 33 < \ 34 typename BOOST_TTI_DETAIL_TP_T, \ 35 typename BOOST_TTI_DETAIL_TP_FALLBACK_ \ 36 = boost::mpl::bool_< BOOST_PP_ARRAY_ELEM(3, args) > \ 37 > \ 38 struct BOOST_PP_ARRAY_ELEM(0, args) \ 39 { \ 40 private: \ 41 introspect_macro(args) \ 42 public: \ 43 static const bool value \ 44 = BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< BOOST_TTI_DETAIL_TP_T >::value; \ 45 typedef typename BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \ 46 < \ 47 BOOST_TTI_DETAIL_TP_T \ 48 >::type type; \ 49 }; \ 50 /**/ 51 52 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1400) 53 54 #define BOOST_TTI_DETAIL_HAS_MEMBER_MULTI_SUBSTITUTE(z,n,args) \ 55 template \ 56 < \ 57 template \ 58 < \ 59 BOOST_PP_ENUM_ ## z \ 60 ( \ 61 BOOST_PP_SUB \ 62 ( \ 63 BOOST_PP_ARRAY_SIZE(args), \ 64 4 \ 65 ), \ 66 BOOST_TTI_DETAIL_TEMPLATE_PARAMETERS, \ 67 args \ 68 ) \ 69 > \ 70 class BOOST_TTI_DETAIL_TM_V \ 71 > \ 72 struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \ 73 { \ 74 }; \ 75 /**/ 76 77 #define BOOST_TTI_DETAIL_HAS_MEMBER_SUBSTITUTE(args) \ 78 BOOST_PP_REPEAT \ 79 ( \ 80 BOOST_PP_ARRAY_ELEM(2, args), \ 81 BOOST_TTI_DETAIL_HAS_MEMBER_MULTI_SUBSTITUTE, \ 82 args \ 83 ) \ 84 /**/ 85 86 #define BOOST_TTI_DETAIL_HAS_MEMBER_INTROSPECT(args) \ 87 template< typename U > \ 88 struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \ 89 { \ 90 BOOST_TTI_DETAIL_HAS_MEMBER_SUBSTITUTE(args) \ 91 BOOST_MPL_HAS_MEMBER_REJECT(args, BOOST_PP_NIL) \ 92 BOOST_MPL_HAS_MEMBER_ACCEPT(args, BOOST_PP_NIL) \ 93 BOOST_STATIC_CONSTANT \ 94 ( \ 95 bool, value = BOOST_MPL_HAS_MEMBER_TEST(args) \ 96 ); \ 97 typedef boost::mpl::bool_< value > type; \ 98 }; \ 99 /**/ 100 101 #define BOOST_TTI_DETAIL_HAS_MEMBER_WITH_FUNCTION_SFINAE(args) \ 102 BOOST_TTI_DETAIL_HAS_MEMBER_IMPLEMENTATION \ 103 ( \ 104 args, \ 105 BOOST_TTI_DETAIL_HAS_MEMBER_INTROSPECT \ 106 ) \ 107 /**/ 108 109 #else // !!BOOST_WORKAROUND(BOOST_MSVC, <= 1400) 110 111 #define BOOST_TTI_DETAIL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE(z,n,args) \ 112 template \ 113 < \ 114 template \ 115 < \ 116 BOOST_PP_ENUM_ ## z \ 117 ( \ 118 BOOST_PP_SUB \ 119 ( \ 120 BOOST_PP_ARRAY_SIZE(args), \ 121 4 \ 122 ), \ 123 BOOST_TTI_DETAIL_TEMPLATE_PARAMETERS, \ 124 args \ 125 ) \ 126 > \ 127 class BOOST_TTI_DETAIL_TM_U \ 128 > \ 129 struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE \ 130 ( \ 131 args, \ 132 n \ 133 ) \ 134 { \ 135 typedef \ 136 BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \ 137 type; \ 138 }; \ 139 /**/ 140 141 #define BOOST_TTI_DETAIL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE(args) \ 142 typedef void \ 143 BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args); \ 144 BOOST_PP_REPEAT \ 145 ( \ 146 BOOST_PP_ARRAY_ELEM(2, args), \ 147 BOOST_TTI_DETAIL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE, \ 148 args \ 149 ) \ 150 /**/ 151 152 #define BOOST_TTI_DETAIL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE(args) \ 153 BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE(args,BOOST_PP_NIL) \ 154 BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE(args,BOOST_PP_NIL) \ 155 template< typename BOOST_TTI_DETAIL_TP_U > \ 156 struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \ 157 : BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< BOOST_TTI_DETAIL_TP_U > { \ 158 }; \ 159 /**/ 160 161 #define BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE(args) \ 162 BOOST_TTI_DETAIL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE \ 163 ( \ 164 args \ 165 ) \ 166 BOOST_TTI_DETAIL_HAS_MEMBER_IMPLEMENTATION \ 167 ( \ 168 args, \ 169 BOOST_TTI_DETAIL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE \ 170 ) \ 171 /**/ 172 173 #endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1400) 174 175 #else // defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) 176 177 #define BOOST_TTI_DETAIL_SAME(trait,name) \ 178 BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF \ 179 ( \ 180 trait, \ 181 name, \ 182 false \ 183 ) \ 184 /**/ 185 186 #define BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS(trait,name,tp) \ 187 BOOST_TTI_DETAIL_SAME(trait,name) \ 188 /**/ 189 190 #endif // !BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE 191 192 #define BOOST_TTI_DETAIL_TRAIT_HAS_TEMPLATE_CHECK_PARAMS_OP(trait,name,tpArray) \ 193 BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS(BOOST_PP_CAT(trait,_detail),name,tpArray) \ 194 template<class BOOST_TTI_DETAIL_TP_T> \ 195 struct BOOST_PP_CAT(trait,_detail_cp_op) : \ 196 BOOST_PP_CAT(trait,_detail)<BOOST_TTI_DETAIL_TP_T> \ 197 { \ 198 }; \ 199 /**/ 200 201 #define BOOST_TTI_DETAIL_TRAIT_HAS_TEMPLATE_CHECK_PARAMS(trait,name,tpArray) \ 202 BOOST_TTI_DETAIL_TRAIT_HAS_TEMPLATE_CHECK_PARAMS_OP(trait,name,tpArray) \ 203 template<class BOOST_TTI_DETAIL_TP_T> \ 204 struct trait \ 205 { \ 206 typedef typename \ 207 boost::mpl::eval_if \ 208 < \ 209 boost::is_class<BOOST_TTI_DETAIL_TP_T>, \ 210 BOOST_PP_CAT(trait,_detail_cp_op)<BOOST_TTI_DETAIL_TP_T>, \ 211 boost::mpl::false_ \ 212 >::type type; \ 213 BOOST_STATIC_CONSTANT(bool,value=type::value); \ 214 }; \ 215 /**/ 216 217 #if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) 218 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1400) 219 220 #define BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS(trait,name,tpArray) \ 221 BOOST_TTI_DETAIL_HAS_MEMBER_WITH_FUNCTION_SFINAE \ 222 ( \ 223 ( BOOST_PP_ADD(BOOST_PP_ARRAY_SIZE(tpArray),4), ( trait, name, 1, false, BOOST_PP_ARRAY_ENUM(tpArray) ) ) \ 224 ) \ 225 /**/ 226 227 #else // BOOST_WORKAROUND(BOOST_MSVC, <= 1400) 228 229 #define BOOST_TTI_DETAIL_TRAIT_CALL_HAS_TEMPLATE_CHECK_PARAMS(trait,name,tpArray) \ 230 BOOST_TTI_DETAIL_HAS_MEMBER_WITH_TEMPLATE_SFINAE \ 231 ( \ 232 ( BOOST_PP_ADD(BOOST_PP_ARRAY_SIZE(tpArray),4), ( trait, name, 1, false, BOOST_PP_ARRAY_ENUM(tpArray) ) ) \ 233 ) \ 234 /**/ 235 236 #endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1400) 237 #endif // !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) 238 239 #endif // BOOST_TTI_DETAIL_TEMPLATE_PARAMS_HPP 240