| 32 | // MSVC and GCC <= 4.4 have a bug that affects partial specializations of |
| 33 | // nested templates under some circumstances. This affects the implementation |
| 34 | // of BOOST_FUSION_DEFINE_STRUCT_INLINE, which uses such specializations for |
| 35 | // the iterator class's 'deref' and 'value_of' metafunctions. On these compilers |
| 36 | // an alternate implementation for these metafunctions is used that does not |
| 37 | // require such specializations. The alternate implementation takes longer |
| 38 | // to compile so its use is restricted to the offending compilers. |
| 39 | // For MSVC, the bug was was reported at https://connect.microsoft.com/VisualStudio/feedback/details/757891/c-compiler-error-involving-partial-specializations-of-nested-templates |
| 40 | // For GCC, 4.4 and earlier are no longer maintained so there is no need |
| 41 | // to report a bug. |
| 42 | #if defined(BOOST_MSVC) || (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 4))) |
| 43 | #define BOOST_FUSION_NEED_NESTED_TEMPLATE_PARTIAL_SPEC_WKND |
| 44 | #endif |
| 45 | |
| 46 | #ifdef BOOST_FUSION_NEED_NESTED_TEMPLATE_PARTIAL_SPEC_WKND |
| 47 | #include <boost/type_traits/add_const.hpp> |
| 48 | #include <boost/type_traits/remove_const.hpp> |
| 49 | #include <boost/mpl/if.hpp> |
| 50 | #include <boost/fusion/sequence/intrinsic/at_c.hpp> |
| 51 | #include <boost/fusion/container/vector.hpp> |
| 52 | #endif |
| 53 | |
| 54 | |
| 176 | #ifdef BOOST_FUSION_NEED_NESTED_TEMPLATE_PARTIAL_SPEC_WKND |
| 177 | |
| 178 | #define BOOST_FUSION_DEFINE_ITERATOR_VALUE_OF(NAME, ATTRIBUTE_SEQ_SIZE) \ |
| 179 | template <typename boost_fusion_detail_Iterator> \ |
| 180 | struct value_of : boost::fusion::result_of::at_c< \ |
| 181 | ref_vec_t, \ |
| 182 | boost_fusion_detail_Iterator::index::value \ |
| 183 | > \ |
| 184 | { \ |
| 185 | }; |
| 186 | |
| 187 | #define BOOST_FUSION_DEFINE_ITERATOR_DEREF(NAME, ATTRIBUTES_SEQ) \ |
| 188 | template <typename boost_fusion_detail_Iterator> \ |
| 189 | struct deref \ |
| 190 | { \ |
| 191 | typedef typename boost::remove_const< \ |
| 192 | boost_fusion_detail_Iterator \ |
| 193 | >::type iterator_raw_type; \ |
| 194 | \ |
| 195 | static const int index = iterator_raw_type::index::value; \ |
| 196 | \ |
| 197 | typedef typename boost::fusion::result_of::at_c< \ |
| 198 | ref_vec_t, \ |
| 199 | index \ |
| 200 | >::type result_raw_type; \ |
| 201 | \ |
| 202 | typedef typename boost::mpl::if_< \ |
| 203 | boost::is_const<typename iterator_raw_type::sequence_type>, \ |
| 204 | typename boost::add_const<result_raw_type>::type, \ |
| 205 | result_raw_type \ |
| 206 | >::type type; \ |
| 207 | \ |
| 208 | static type call(iterator_raw_type const& iter) \ |
| 209 | { \ |
| 210 | return boost::fusion::at_c<index>(iter.ref_vec); \ |
| 211 | } \ |
| 212 | }; |
| 213 | |
| 214 | #define BOOST_FUSION_MAKE_ITERATOR_WKND_FIELD_NAME(R, DATA, N, ATTRIBUTE) \ |
| 215 | BOOST_PP_COMMA_IF(N) seq.BOOST_PP_TUPLE_ELEM(2, 1, ATTRIBUTE) |
| 216 | |
| 217 | #define BOOST_FUSION_DEFINE_ITERATOR_WKND_INIT_LIST_ENTRIES(ATTRIBUTES_SEQ) \ |
| 218 | , ref_vec(BOOST_PP_SEQ_FOR_EACH_I( \ |
| 219 | BOOST_FUSION_MAKE_ITERATOR_WKND_FIELD_NAME, \ |
| 220 | ~, \ |
| 221 | BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ))) |
| 222 | |
| 223 | #define BOOST_FUSION_MAKE_ITERATOR_WKND_REF(Z, N, DATA) \ |
| 224 | BOOST_PP_COMMA_IF(N) \ |
| 225 | typename boost::mpl::if_< \ |
| 226 | boost::is_const<boost_fusion_detail_Seq>, \ |
| 227 | typename boost::add_const< \ |
| 228 | typename boost_fusion_detail_Seq::t##N##_type \ |
| 229 | >::type, \ |
| 230 | typename boost_fusion_detail_Seq::t##N##_type \ |
| 231 | >::type& |
| 232 | |
| 233 | #define BOOST_FUSION_DEFINE_ITERATOR_WKND_MEMBERS(ATTRIBUTES_SEQ_SIZE) \ |
| 234 | typedef boost::fusion::vector< \ |
| 235 | BOOST_PP_REPEAT( \ |
| 236 | ATTRIBUTES_SEQ_SIZE, \ |
| 237 | BOOST_FUSION_MAKE_ITERATOR_WKND_REF, \ |
| 238 | ~) \ |
| 239 | > ref_vec_t; \ |
| 240 | \ |
| 241 | ref_vec_t ref_vec; |
| 242 | |
| 243 | #else |
| 244 | |
| 245 | #define BOOST_FUSION_DEFINE_ITERATOR_VALUE_OF(NAME, ATTRIBUTES_SEQ_SIZE) \ |
| 246 | template <typename boost_fusion_detail_T> struct value_of; \ |
| 247 | BOOST_PP_REPEAT( \ |
| 248 | ATTRIBUTES_SEQ_SIZE, \ |
| 249 | BOOST_FUSION_MAKE_ITERATOR_VALUE_OF_SPECS, \ |
| 250 | NAME) |
| 251 | |
| 252 | #define BOOST_FUSION_DEFINE_ITERATOR_DEREF(NAME, ATTRIBUTES_SEQ) \ |
| 253 | template <typename boost_fusion_detail_T> struct deref; \ |
| 254 | BOOST_PP_SEQ_FOR_EACH_I( \ |
| 255 | BOOST_FUSION_MAKE_ITERATOR_DEREF_SPECS, \ |
| 256 | NAME, \ |
| 257 | ATTRIBUTES_SEQ) |
| 258 | |
| 259 | #define BOOST_FUSION_DEFINE_ITERATOR_WKND_INIT_LIST_ENTRIES(ATTRIBUTES_SEQ) |
| 260 | |
| 261 | #define BOOST_FUSION_DEFINE_ITERATOR_WKND_MEMBERS(ATTRIBUTES_SEQ_SIZE) |
| 262 | |
| 263 | #endif // BOOST_FUSION_NEED_NESTED_TEMPLATE_PARTIAL_SPEC_WKND |
| 264 | |