A Day of Achievement – Cartesian Product with Boost.MPL

Today is a day worthy of celebration, as I finally solved a problem I’ve been working on for quite some time.  See it here.

Code:

#ifndef TRI_TYPE_CARTESIAN_PRODUCT_H
#define TRI_TYPE_CARTESIAN_PRODUCT_H

#include <boost/mpl/vector.hpp>

#include <typeinfo>

namespace recursive
{
    using boost::is_same;
    using boost::mpl::begin;
    using boost::mpl::end;
    using boost::mpl::next;        
    using boost::mpl::if_;  
    using boost::mpl::deref;    
    using boost::mpl::size;
    using boost::mpl::advance;  
    using boost::mpl::int_;  
    
    namespace detail
    {
        unsigned int total_recursions = 0;

        struct end_of_recursion_tag 
        {
            static void Run()
            {
                std::cout << "end of " 
                     << total_recursions 
                     << " recursions\n"
                    ;
                    
                total_recursions = 0;
            }
        };    
    }
    
    // generate a Cartesian Product of 3 type sequences and apply TestFunc on each generated type
    template <
        class UTypes,    // Forward Sequence, e.g. boost::mpl::vector
        class VTypes,    // Forward Sequence, e.g. boost::mpl::vector
        class WTypes,    // Forward Sequence, e.g. boost::mpl::vector
        class TestFunc  // class type that has a nested templated run() member function
    >
    struct CartesianProduct
    {
        // forward declaration
        template <
            class UIterator,
            class VIterator,
            class WIterator 
        >   
        class Generate;

        // this class implements recursion body 
        template <
            class UIterator,
            class VIterator,
            class WIterator
        >            
        struct Next
        {
            // u_begin is not necessary 😉
            // it would be cheaper not to pre-declare all of them since we force evaluation
            // however this dramatically increase the readability
            typedef typename begin<VTypes>::type v_begin;
            typedef typename begin<WTypes>::type w_begin;

            typedef typename end<UTypes>::type u_end;
            typedef typename end<VTypes>::type v_end;
            typedef typename end<WTypes>::type w_end;

            typedef typename next<UIterator>::type u_next;
            typedef typename next<VIterator>::type v_next;
            typedef typename next<WIterator>::type w_next;
        
            typedef typename if_< is_same<typename w_next, w_end>,
                                typename if_< is_same<v_next, v_end>,
                                    typename if_< is_same<u_next, u_end>,
                                        detail::end_of_recursion_tag,
                                        Generate< 
                                            u_next, 
                                            v_begin, 
                                            w_begin 
                                        >
                                    >::type,
                                    Generate< 
                                        UIterator, 
                                        v_next,
                                        w_begin 
                                    >
                                >::type,
                                Generate< 
                                    UIterator, 
                                    VIterator, 
                                    w_next
                                    >
                            >::type type;
        };
        
        //  this class run test on generated types in thos round and go to next*/
        template <
            class UIterator = typename begin<UTypes>::type,
            class VIterator = typename begin<VTypes>::type,
            class WIterator = typename begin<WTypes>::type
        >
        struct Generate
        {
            //  generate <<next>> target type         
            typedef typename Next<
                    UIterator, 
                    VIterator, 
                    WIterator 
                >::type next_type;

            static void Run()
            {
                // increment recursion counter                
                ++detail::total_recursions;
                
                // test on the generated types of this round of recursion
                TestFunc::run<
                     typename deref<UIterator>::type,
                     typename deref<VIterator>::type,
                     typename deref<WIterator>::type
                 >();

                // go to the next round of recursion
                next_type::Run();
            }
        };
    
        template <
            size_t UIndex = 0,
            size_t VIndex = 0,
            size_t WIndex = 0
        >
        struct GenerateByIndex
        {                
            static_assert(UIndex <= size<UTypes>::type::value, "too large stock container index");
            static_assert(VIndex <= size<VTypes>::type::value, "too large stock shrinker_group_number index");
            static_assert(WIndex <= size<WTypes>::type::value, "too large stock shrinker_group_size index");

            typedef typename begin<UTypes>::type u_begin;        
            typedef typename begin<VTypes>::type v_begin;
            typedef typename begin<WTypes>::type w_begin;         
    
            static void Run()
            {  
                Generate<
                    typename advance<u_begin, int_<UIndex> >::type,
                    typename advance<v_begin, int_<VIndex> >::type,
                    typename advance<w_begin, int_<WIndex> >::type                    
                >::Run();
            }
        };                
    };
    
    struct print_typeid
    {
        template<
            class U, 
            class V, 
            class W
        >
        static void run()
        {
            // print the typeinfo
            std::cout 
                <<  detail::total_recursions << ":"
                << typeid(U).name() << ","
                << typeid(V).name() << ","
                << typeid(W).name()
                << std::endl;  
        }            
    }; 
    
}//  namespace recursive_test

#endif

Advertisements
Post a comment or leave a trackback: Trackback URL.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: