Вот альтернативное решение, вдохновленное ответом Люка Турэля .
Эта версия выполняется с использованием классов метафункций вместо функций, которые позволяют вызывать static_for_each
даже вне областей функций (полезно, если работа должна быть полностью выполнена во время компиляции, поэтому у вас нет ненужных функции, вызываемые во время выполнения).
Более того, он дает больше взаимодействия благодаря типам first
и last
, позволяющим при необходимости извлекать информацию из цикла, немного похоже на то, как return
работает для функции.
Вы также можете получить доступ к предыдущему результату итерации в каждой итерации благодаря второму параметру шаблона Previous
, переданному в класс метафункций F
.
Наконец, вы можете предоставить данные процессу цикла, используя параметр шаблона Initial
, он будет задан как значение параметра Previous
первой итерации.
# 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;
};
Вот простой пример, который дает и получает данные:
# 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);
}
Эти функции делают использование static_for_each
более похожим на использование обычных циклов выполнения (while
, for
, BOOST_FOREACH ...), поскольку вы можете более напрямую взаимодействовать с циклом .