Here is an alternative solution highly inspired from Luc Touraille's answer.
This version is done using Metafunction classes instead of functions which allows the static_for_each
to be called even outside of function scopes (useful if the job has to be totally done at compiletime so you have no unnecessary functions called at runtime).
Furthermore it gives more interaction thanks to the first
and last
typedefs, allowing to get information out of the loop if necessary, a little like the way a return
works for a function.
You can also access the previous iteration result within each iteration thanks to the second template parameter Previous
passed to the metafunction class F
.
Finally you can provide data to the loop process using the Initial
template parameter, it will be given as the value of the Previous
parameter of the first iteration.
# include <boost/mpl/begin_end.hpp>
# include <boost/mpl/next_prior.hpp>
# include <boost/mpl/apply.hpp>
namespace detail_static_for_each
{
// Loop
template<typename Begin, typename End, typename F, typename Previous>
struct static_for_each
{
private:
typedef typename Begin::type current_type;
public:
typedef typename boost::mpl::apply<F, current_type, Previous>::type first;
typedef typename static_for_each<typename boost::mpl::next<Begin>::type, End, F, first>::last last;
};
// End of loop
template<typename End, typename F, typename Last>
struct static_for_each<End, End, F, Last>
{
public:
typedef Last first;
typedef Last last;
};
} // namespace detail_static_for_each
// Public interface
template<typename Sequence, typename F, typename Initial = void>
struct static_for_each
{
private:
typedef typename boost::mpl::begin<Sequence>::type begin;
typedef typename boost::mpl::end<Sequence>::type end;
typedef typename detail_static_for_each::static_for_each<begin, end, F, Initial> loop;
public:
typedef typename loop::first first;
typedef typename loop::last last;
};
Here is a simple example that both gives and retrieves data :
# include <iostream>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/vector.hpp>
# include "static_for_each.hpp"
struct is_there_a_float
{
template<typename currentItem, typename PreviousIterationType>
struct apply
{
typedef typename boost::mpl::if_< PreviousIterationType,
PreviousIterationType,
boost::is_same<float, currentItem> >::type type;
};
};
struct test
{
typedef boost::mpl::vector< char, long, long, double, float, int, char > sequence;
typedef static_for_each<sequence, is_there_a_float, boost::false_type>::last found;
};
int main(void)
{
std::cout << std::boolalpha << test::found::value << std::endl;
return (0);
}
These features makes the use of static_for_each
more similar to the use of common runtime loops (while
, for
, BOOST_FOREACH ...) as you can interact more directly with the loop.