|
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