Ticket #7569: define-struct-inline-msvc-wknd.patch

File define-struct-inline-msvc-wknd.patch, 10.7 KB (added by zeratul976@…, 10 years ago)

Patch that implements the workaround

  • boost/fusion/adapted/struct/detail/define_struct_inline.hpp

     
    88#ifndef BOOST_FUSION_ADAPTED_STRUCT_DETAIL_DEFINE_STRUCT_INLINE_HPP
    99#define BOOST_FUSION_ADAPTED_STRUCT_DETAIL_DEFINE_STRUCT_INLINE_HPP
    1010
     11#include <boost/config.hpp>
    1112#include <boost/fusion/support/category_of.hpp>
    1213#include <boost/fusion/sequence/sequence_facade.hpp>
    1314#include <boost/fusion/iterator/iterator_facade.hpp>
     
    2526#include <boost/preprocessor/seq/for_each_i.hpp>
    2627#include <boost/preprocessor/seq/size.hpp>
    2728#include <boost/preprocessor/seq/enum.hpp>
     29#include <boost/preprocessor/seq/seq.hpp>
    2830#include <boost/preprocessor/tuple/elem.hpp>
    2931
     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
    3055#define BOOST_FUSION_MAKE_DEFAULT_INIT_LIST_ENTRY(R, DATA, N, ATTRIBUTE)        \
    3156    BOOST_PP_COMMA_IF(N) BOOST_PP_TUPLE_ELEM(2, 1, ATTRIBUTE)()
    3257
     
    148173#define BOOST_FUSION_MAKE_DATA_MEMBER(R, DATA, N, ATTRIBUTE)                    \
    149174    BOOST_PP_TUPLE_ELEM(2, 0, ATTRIBUTE) BOOST_PP_TUPLE_ELEM(2, 1, ATTRIBUTE);
    150175
     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
    151265// Note: We can't nest the iterator inside the struct because we run into
    152266//       a MSVC10 bug involving partial specializations of nested templates.
    153267
     
    219333        typedef boost_fusion_detail_Seq sequence_type;                          \
    220334                                                                                \
    221335        BOOST_FUSION_ITERATOR_NAME(NAME)(boost_fusion_detail_Seq& seq)          \
    222             : seq_(seq) {}                                                      \
     336            : seq_(seq)                                                         \
     337              BOOST_FUSION_DEFINE_ITERATOR_WKND_INIT_LIST_ENTRIES(              \
     338                      (0)ATTRIBUTES_SEQ)                                        \
     339        {}                                                                      \
    223340                                                                                \
    224341        boost_fusion_detail_Seq& seq_;                                          \
    225342                                                                                \
    226         template <typename boost_fusion_detail_T> struct value_of;              \
    227         BOOST_PP_REPEAT(                                                        \
    228             ATTRIBUTES_SEQ_SIZE,                                                \
    229             BOOST_FUSION_MAKE_ITERATOR_VALUE_OF_SPECS,                          \
    230             NAME)                                                               \
     343        BOOST_FUSION_DEFINE_ITERATOR_WKND_MEMBERS(ATTRIBUTES_SEQ_SIZE)          \
    231344                                                                                \
    232         template <typename boost_fusion_detail_T> struct deref;                 \
    233         BOOST_PP_SEQ_FOR_EACH_I(                                                \
    234             BOOST_FUSION_MAKE_ITERATOR_DEREF_SPECS,                             \
    235             NAME,                                                               \
    236             ATTRIBUTES_SEQ)                                                     \
     345        BOOST_FUSION_DEFINE_ITERATOR_VALUE_OF(NAME, ATTRIBUTES_SEQ_SIZE)        \
    237346                                                                                \
     347        BOOST_FUSION_DEFINE_ITERATOR_DEREF(NAME, ATTRIBUTES_SEQ)                \
     348                                                                                \
    238349        template <typename boost_fusion_detail_It>                              \
    239350        struct next                                                             \
    240351        {                                                                       \