这里有一个备选方案,受到了Luc Touraille's answer的启发。
这个版本使用元函数类而不是函数来完成,这使得static_for_each
可以在函数作用域之外被调用(如果工作必须完全在编译时完成,这将非常有用,因为你不需要在运行时调用不必要的函数)。
此外,由于first
和last
typedefs的存在,它提供了更多的交互性,允许在必要时从循环中获取信息,有点像函数的return
的工作方式。
你还可以通过传递给元函数类F
的第二个模板参数Previous
来在每次迭代中访问前一次迭代的结果。
最后,你可以使用Initial
模板参数向循环过程提供数据,它将作为第一次迭代的Previous
参数的值。
# include <boost/mpl/begin_end.hpp>
# include <boost/mpl/next_prior.hpp>
# include <boost/mpl/apply.hpp>
namespace detail_static_for_each
{
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;
};
template<typename End, typename F, typename Last>
struct static_for_each<End, End, F, Last>
{
public:
typedef Last first;
typedef Last last;
};
}
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;
};
这里有一个简单的例子,既可以提供数据,也可以检索数据:
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 ...),因为您可以更直接地与循环交互。
mpl::transform
来即时定义“指针”版本:boost :: mpl :: for_each <boost :: mpl :: transform <MyTypes,boost :: add_pointer <boost :: mpl :: _1> :: type >(Functor())
。 - kizzx2