[MPL/Fusion?]Call a 0-args template function on members of a sequence

Hello all, I have the following: template<typename T> void f() { /* ... */ } typedef boost::mpl::vector<int, long, double> my_vec; I'm looking for a way to call f<T>() for all types T in my_vec. I initially hoped that either an mpl algorithm or fusion::for_each might be able to accomplish this for me, but after reading through their docs this doesn't appear to be the case. Am I correct in this conclusion? If not, I'd really appreciate someone giving me a quick pointer as to what I need to do. Currently I'm using the specialization/static-recursion trick. Something like: template<typename types, int idx, int size> struct helper { static void call_f() { using namespace boost::mpl; f< at<types, int_<idx>::type >::type >(); helper<types, idx + 1, size>::call_f(); // recurse } }; template<typename types, int size> struct helper<types, size, size> { static void call_f() { } // end recursion }; void call_f_with_each_type() { enum { num_types = size<my_vec>::type::value }; helper<my_vec, 0, num_types>::call_f(); } It works fine, but I'm wondering if there's a more succinct and readable way. Kind regards, Edd

Edd Dawson <edd@nunswithguns.net> writes:
Hello all,
I have the following:
template<typename T> void f() { /* ... */ }
typedef boost::mpl::vector<int, long, double> my_vec;
I'm looking for a way to call f<T>() for all types T in my_vec. I initially hoped that either an mpl algorithm or fusion::for_each might be able to accomplish this for me, but after reading through their docs this doesn't appear to be the case.
struct call_f { template <class Wrapper> void operator()(Wrapper) { f<typename Wrapper::type>(); } }; mpl::for_each<my_vec, mpl::identity<_> >(call_f()); HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams <dave@boost-consulting.com> writes:
Edd Dawson <edd@nunswithguns.net> writes:
Hello all,
I have the following:
template<typename T> void f() { /* ... */ }
typedef boost::mpl::vector<int, long, double> my_vec;
I'm looking for a way to call f<T>() for all types T in my_vec. I initially hoped that either an mpl algorithm or fusion::for_each might be able to accomplish this for me, but after reading through their docs this doesn't appear to be the case.
struct call_f { template <class Wrapper> void operator()(Wrapper) Sorry, it's missing a "const" right here--^^^^ { f<typename Wrapper::type>(); } };
mpl::for_each<my_vec, mpl::identity<_> >(call_f());
-- Dave Abrahams Boost Consulting www.boost-consulting.com

Hi Dave, Thanks for your reply. David Abrahams wrote:
David Abrahams <dave@boost-consulting.com> writes:
Edd Dawson <edd@nunswithguns.net> writes:
Hello all,
I have the following:
template<typename T> void f() { /* ... */ }
typedef boost::mpl::vector<int, long, double> my_vec;
I'm looking for a way to call f<T>() for all types T in my_vec. I initially hoped that either an mpl algorithm or fusion::for_each might be able to accomplish this for me, but after reading through their docs this doesn't appear to be the case. struct call_f { template <class Wrapper> void operator()(Wrapper) Sorry, it's missing a "const" right here--^^^^ { f<typename Wrapper::type>(); } };
mpl::for_each<my_vec, mpl::identity<_> >(call_f());
I didn't find this in the docs. Is it meant to be there? Unfortunately, that didn't quite work for me, anyway. A requirement of for_each (according to my MSVC 8 diagnostics) is that each type in the sequence must be default constructible. The (near) exact code I'm trying to compile is: struct register_cage { template<typename wrapper> void operator()(wrapper) const { // ... } }; struct null_type { }; // template<typename T1 = null_type, ..., typename TN = null_type> template< BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_LIMIT_VECTOR_SIZE, typename T, null_type) > struct catch_exceptions { typedef typename boost::mpl::vector< BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_VECTOR_SIZE, T) >::type exception_types; catch_exceptions() { using namespace boost::mpl; typedef boost::mpl::_1 my1; typedef boost::mpl::_2 my2; // Remove all null_type entries and then sort the remaining ones, // most derived to front. typedef remove_if< exception_types, boost::is_same<_, null_type> >::type unique_exception_types; typedef sort< unique_exception_types, boost::is_base_of<my2, my1> >::type sorted_exception_types; for_each<sorted_exception_types, identity<_> >(register_cage()); } }; // Elsewhere, in 'client' code catch_exceptions<std::exception, std::runtime_error>(); The most appropriate part of the (long) compiler error is: 1>c:\development\boost\include\boost-1_33_1\boost\utility\value_init.hpp(34) : error C2512: 'std::runtime_error' : no appropriate default constructor available 1> c:\development\boost\include\boost-1_33_1\boost\utility\value_init.hpp(34) : while compiling class template member function 'boost::vinit_detail::non_const_T_base<T>::non_const_T_base(void)' Assuming that I have interpreted the compiler errors correctly, is this default-constructible requirement really necessary? I can do the task using the trick I listed in my original post so I would expect a library of this kind to be able to. Kind regards, Edd

Edd Dawson <edd@nunswithguns.net> writes:
I'm looking for a way to call f<T>() for all types T in my_vec. I initially hoped that either an mpl algorithm or fusion::for_each might be able to accomplish this for me, but after reading through their docs this doesn't appear to be the case. struct call_f { template <class Wrapper> void operator()(Wrapper) Sorry, it's missing a "const" right here--^^^^ { f<typename Wrapper::type>(); } };
mpl::for_each<my_vec, mpl::identity<_> >(call_f());
I didn't find this in the docs. Is it meant to be there?
The specific answer to your specific problem? No. Oh yeah, for_each wasn't documented in 1.33.1... and apparently it isn't documented in the CVS head either (still? Aleksey?)
Unfortunately, that didn't quite work for me, anyway. A requirement of for_each (according to my MSVC 8 diagnostics) is that each type in the sequence must be default constructible.
In the case above, only mpl::identity<T> needs to be default-constructible for each type in the list... or that was my intention Ach! My mistake... template <class T> struct make_identity { typedef mpl::identity<T> type; }; mpl::for_each<my_vec, make_identity<_> >(call_f()); should work. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
struct call_f { template <class Wrapper> void operator()(Wrapper) Sorry, it's missing a "const" right here--^^^^ { f<typename Wrapper::type>(); } };
mpl::for_each<my_vec, mpl::identity<_> >(call_f()); I didn't find this in the docs. Is it meant to be there?
The specific answer to your specific problem? No. Oh yeah, for_each wasn't documented in 1.33.1... and apparently it isn't documented in the CVS head either (still? Aleksey?)
Yep, I was referring to mpl::for_each in general.
Unfortunately, that didn't quite work for me, anyway. A requirement of for_each (according to my MSVC 8 diagnostics) is that each type in the sequence must be default constructible.
In the case above, only mpl::identity<T> needs to be default-constructible for each type in the list... or that was my intention Ach! My mistake...
template <class T> struct make_identity { typedef mpl::identity<T> type; };
mpl::for_each<my_vec, make_identity<_> >(call_f());
should work.
Like a charm! Many thanks! Kind Regards, Edd
participants (2)
-
David Abrahams
-
Edd Dawson