Ecco una soluzione alternativa altamente ispirato Luc Touraille's answer.
Questa versione viene fatto utilizzando Metafunction classes invece di funzioni che consente al static_for_each
di essere chiamato anche al di fuori di ambiti di funzione (utile se il lavoro deve essere totalmente fatto a compiletime modo da non avere funzioni inutili chiamate a runtime).
Inoltre dà una maggiore interazione grazie ai first
e last
typedef, che consente di ottenere informazioni fuori dal giro, se necessario, un po 'come il modo in cui una return
lavori per una funzione.
È anche possibile accedere al risultato di iterazione precedente all'interno di ciascuna iterazione grazie al secondo parametro di modello Previous
passato alla classe di metafunzione F
.
Infine è possibile fornire dati al processo di loop utilizzando il parametro di modello Initial
, verrà assegnato come valore del parametro Previous
della prima iterazione.
# 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;
};
Ecco un semplice esempio che dà e recupera i dati:
# 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);
}
Queste caratteristiche rende l'uso di static_for_each
più simile all'uso di anelli di runtime comune (while
, for
, BOOST_FOREACH .. .) come puoi interagire più direttamente con il ciclo.
Guida molto utile qui. Grazie. – Marcin