Implementing meta-function zip in c++11

后端 未结 2 1694
名媛妹妹
名媛妹妹 2021-02-02 15:20

I am actually trying to see if I can get a minimal library that supports the very few operations I use from boost::fusion.

Here is what I have so far...



        
2条回答
  •  谎友^
    谎友^ (楼主)
    2021-02-02 15:29

    Seems to be doable with fully-fledged lists (that means head, tail and cons operations) and recursion. Tested with a snapshot of GCC 4.7, all the std stuff is from :

    struct nil {};
    
    template
    struct is_nil: std::is_same {};
    
    template
    struct and_: std::true_type {};
    
    template
    struct and_
    : std::integral_constant<
        bool
        , First::value && and_::value
    > {};
    
    template
    struct not_
    : std::integral_constant {};
    
    template
    struct typelist;
    
    template
    struct typelist {
        typedef First head;
        typedef typelist tail;
    };
    
    template
    struct typelist {
        typedef Last head;
        typedef nil tail;
    };
    
    template
    struct cons;
    
    template
    struct cons> {
        typedef typelist type;
    };
    
    // workaround for:
    // sorry, unimplemented: cannot expand '...' into a fixed-length argument list
    template class Template, typename... T>
    struct gcc_workaround {
        typedef Template type;
    };
    
    namespace detail {
    
    template
    struct zip;
    
    template
    struct zip<
        typename std::enable_if...>::value>::type
        , Lists...
    > {
        typedef typelist> type;
    };
    
    template
    struct zip<
        typename std::enable_if>...>::value>::type
        , Lists...
    > {
        typedef typename cons<
            typelist
            , typename gcc_workaround::type::type
        >::type type;
    };
    
    } // detail
    
    template
    struct zip: detail::zip {};
    

    You might want to add error checking to all this (I'm thinking of invalid instantiations that are currently simply left as incomplete types). Frankly given the amount of time it took me to figure this out, I'd suggest sticking with Boost.MPL. Things like lazy evaluation (with which I wouldn't have needed to do the SFINAE stuff) are a boon and I'd don't like reinventing them. Plus the day it's C++11 enabled you reap the best of both worlds.


    I forgot to mention that Boost.MPL also has the advantages of genericity. It can work on any type that satisfies one of its sequence concept (it's also possible to non-intrusively adapt a preexisting type), whereas you force the use of typelist.

提交回复
热议问题