Aquí hay una solución alternativa altamente inspirada en Luc Touraille's answer. Metafunction classes Esta función se realiza utilizando Metafunction classes en lugar de funciones que permiten llamar al static_for_each
incluso fuera de los ámbitos funcionales (útil si el trabajo debe realizarse totalmente en tiempo de compilación para que no haya funciones innecesarias llamadas en tiempo de ejecución).
Además se da una mayor interacción gracias a los first
y last
typedefs, lo que permite obtener información fuera del circuito, si es necesario, un poco como la forma en que un return
obras para una función.
También puede acceder al resultado de la iteración anterior dentro de cada iteración gracias al segundo parámetro de plantilla Previous
que se pasó a la clase de metafunción F
.
Finalmente, puede proporcionar datos para el proceso de bucle mediante el parámetro de plantilla Initial
, que se proporcionará como el valor del parámetro Previous
de la primera iteración.
# 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;
};
Aquí está un ejemplo sencillo que tanto da y recupera datos:
# 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);
}
Estas características hace que el uso de static_for_each
más similar a la utilización de los bucles de ejecución común (while
, for
, BOOST_FOREACH .. .) ya que puedes interactuar más directamente con el ciclo.
Muy útil orientación aquí. Gracias. – Marcin