Boost logo

Boost Users :

Subject: Re: [Boost-users] Template operator() overloading for types in a
From: Tan, Tom (Shanghai) (TTan_at_[hidden])
Date: 2009-11-03 01:03:07


>And so on ... Could you help me to have an efficient way to do this for
all
>types 'rgb_image_types' without writing each specialization ?

Your situation seems similar to the one discussed here:
http://stackoverflow.com/questions/1492204/is-it-possible-to-generate-ty
pes-with-all-combinations-of-template-arguments.

I actually refined the idea and modeled the mpl::for_each, and came up
with this code pasted below for your reference.What you need to modify
is to reduce the template arguments from 3 to 2 to suit your needs, hope
it helps.

#ifndef FOR_EACH_CARTESIAN_PRODUCT_H
#define FOR_EACH_CARTESIAN_PRODUCT_H

#include <boost/mpl/vector.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/type_traits/is_integral.hpp>
 
#include <iostream>
 
#include <typeinfo>

/*
usage 1:
       typedef recursive::for_each_cartesian-product<
            stock::map_containers,
            stock::shrinker_equal_filters,
            stock::shrinker_method_tags,
            RunnableBody
> benchmark_type;
        
        benchmark_type::run_all();
        
 usage 2:
       typedef recursive::for_each_cartesian-product<
            stock::map_containers,
            stock::shrinker_equal_filters,
            stock::shrinker_method_tags,
            RunnableBody
>::each_product<> benchmark_type;
        
        benchmark_type::run();
*/

namespace recursive
{
    using boost::is_same;
    using boost::is_integral;
    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::distance;
    using boost::mpl::int_;
    using boost::mpl::eval_if_c;
    
    namespace detail
    {
        static unsigned int total_recursions = 0;
    }
    
    // generate a Cartesian Product of 3 type sequences and apply
RunnableBody 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 RunnableBody // class type that has a nested templated
run() member function
>
    struct for_each_cartesian_product
    {
        // forward declaration
        template <
            class UIterator,
            class VIterator,
            class WIterator
>
        class each_product;

        struct end_of_recursion_tag
        {
            static void run(RunnableBody& f)
            {
            #ifndef NDEBUG
                std::cout << "End of "
                    << detail::total_recursions
                    << " recursions: RunnableBody = "
                    << typeid(RunnableBody).name()
                    << std::endl;
            #endif
                detail::total_recursions = 0;
            }
        };

        // convenient interface to run RunnableBody on all generated
types
        static void run_all(RunnableBody& f = RunnableBody())
        {
            each_product<>::run(f);
        }

        // this class implements recursion body
        template <
            class UIterator,
            class VIterator,
            class WIterator
>
        struct next_product
        {
            // 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>,
                                        end_of_recursion_tag,
                                        each_product<
                                            u_next,
                                            v_begin,
                                            w_begin
>
>::type,
                                    each_product<
                                        UIterator,
                                        v_next,
                                        w_begin
>
>::type,
                                each_product<
                                    UIterator,
                                    VIterator,
                                    w_next
>
>::type type;
        };
        
        // interface
        // 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 each_product
        {
            // publc accessible internals of this type
            typedef typename each_product<
                UIterator,
                VIterator,
                WIterator
> this_type;
            
            // types
            typedef typename deref<UIterator>::type UType;
            typedef typename deref<VIterator>::type VType;
            typedef typename deref<WIterator>::type WType;

            // index types
            typedef typename distance<typename begin<UTypes>::type,
UIterator>::type UIndexType;
            typedef typename distance<typename begin<VTypes>::type,
VIterator>::type VIndexType;
            typedef typename distance<typename begin<WTypes>::type,
WIterator>::type WIndexType;
            
            // core
            static void run(RunnableBody& f = RunnableBody())
            {
                // increment recursion counter
                ++detail::total_recursions;
                           
                //f.template <this_type>();
                f.operator()<this_type>();
                 
                // generate <<next>> target type and go to the next
round of recursion
                typedef typename next_product<
                        UIterator,
                        VIterator,
                        WIterator
>::type next_type;
                next_type::run(f);
            }
        };
    
        // alternative interface
        template <
            size_t UIndex = 0,
            size_t VIndex = 0,
            size_t WIndex = 0
>
        struct each_product_by_index
        {
            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(RunnableBody& f = RunnableBody())
            {
                // delegate to iterator-version
                each_product<
                    typename advance<u_begin, int_<UIndex> >::type,
                    typename advance<v_begin, int_<VIndex> >::type,
                    typename advance<w_begin, int_<WIndex> >::type
>::run(f);
            }
        };
    };
    
    // an example test function class impl.
    struct print_typeid
    {
        template< class T>
        void operator()() const
        {
            typedef typename T::UType U;
            typedef typename T::VType V;
            typedef typename T::WType W;
            
            typedef typename T::UIndexType UIndex;
            typedef typename T::VIndexType VIndex;
            typedef typename T::WIndexType WIndex;
            
            // print the typeinfo
            std::cout << "this is a demo implementation.\n";
            std::cout
                << detail::total_recursions
                << "["
                << UIndex::value ", "
                << VIndex::value ", "
                << WIndex::value
                << "]"
                << ": "
                << typeid(U).name() << ","
                << typeid(V).name() << ","
                << typeid(W).name()
                << std::endl;
        }
    };
    
}// namespace recursive_test


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net