Commit 051c267f authored by Tiago Peixoto's avatar Tiago Peixoto

Remove more recursions in nested_for_each()

This reduces even more compilation time and memory use.
parent 09db85b3
Pipeline #62 failed with stage
......@@ -377,43 +377,27 @@ struct action_wrap
: _a(a), _g(g), _max_v(max_v), _max_e(max_e) {}
template <class Type>
boost::checked_vector_property_map<Type,GraphInterface::vertex_index_map_t>&
uncheck(boost::checked_vector_property_map
<Type,GraphInterface::vertex_index_map_t>& a, boost::mpl::true_) const
{
return a;
}
template <class Type>
boost::unchecked_vector_property_map<Type,GraphInterface::vertex_index_map_t>
uncheck(boost::checked_vector_property_map
<Type,GraphInterface::vertex_index_map_t> a, boost::mpl::false_) const
auto
uncheck(boost::checked_vector_property_map<Type, GraphInterface::vertex_index_map_t> a,
boost::mpl::false_) const
{
return a.get_unchecked(_max_v);
}
template <class Type>
boost::checked_vector_property_map<Type,GraphInterface::edge_index_map_t>&
uncheck(boost::checked_vector_property_map
<Type,GraphInterface::edge_index_map_t>& a, boost::mpl::true_) const
{
return a;
}
template <class Type>
boost::unchecked_vector_property_map<Type,GraphInterface::edge_index_map_t>
uncheck(boost::checked_vector_property_map
<Type,GraphInterface::edge_index_map_t> a, boost::mpl::false_) const
auto
uncheck(boost::checked_vector_property_map<Type,GraphInterface::edge_index_map_t> a,
boost::mpl::false_) const
{
return a.get_unchecked(_max_e);
}
template <class Type>
scalarS<typename Type::unchecked_t>
auto
uncheck(scalarS<Type> a, boost::mpl::false_) const
{
return scalarS<typename Type::unchecked_t>(uncheck(a._pmap,
boost::mpl::false_()));
return scalarS<typename Type::unchecked_t>
(uncheck(a._pmap, boost::mpl::false_()));
}
//no op
......@@ -422,14 +406,10 @@ struct action_wrap
void operator()() const {};
template <class T1> void operator()(T1* a1) const
{ _a(*a1); }
template <class T1, class... Ts>
void operator()(T1* a1, Ts&&... as) const
{
_a(*a1, uncheck(std::forward<Ts>(as), Wrap())...);
}
Action _a;
......
......@@ -54,105 +54,95 @@ namespace mpl
//
// The code above will run iterate through all combinations of foo::operator(T1,
// T2, T3) and call the one that corresponds to the actual types stored in x, y,
// and z. If the types are not found during iteration, we have found = true,
// otherwise found = false. This provides a more general compile-time to
// and z. If the types are not found during iteration, we have found == true,
// otherwise found == false. This provides a more general compile-time to
// run-time bridge than the simpler mpl::for_each().
template <class Action, class T>
struct bind_arg
struct stop_iteration: public std::exception {};
// this is a functor wrapper that will perform an any_cast<> in each in an array
// of arguments according to the called types. If the cast is successful, the
// function will be called with those types, and stop_iteration will be thrown.
template <class Action, std::size_t N>
struct all_any_cast
{
bind_arg(Action a, any& arg, bool& found)
: _a(a), _arg(arg), _found(found) {}
all_any_cast(Action a, std::array<any, N>& args)
: _a(a), _args(args) {}
template <class... Ts>
__attribute__((always_inline))
void operator()(Ts&&... args) const
void operator()(Ts&&... vs) const
{
T* v = const_cast<T*>(any_cast<T>(&_arg));
if (v != 0)
_a(*v, args...);
dispatch(std::make_index_sequence<sizeof...(Ts)>(),
std::forward<Ts>(vs)...);
}
template <std::size_t... Idx, class... Ts>
__attribute__((always_inline))
void operator()() const
void dispatch(std::index_sequence<Idx...>, Ts&&...) const
{
T* v = const_cast<T*>(any_cast<T>(&_arg));
if (v != 0)
try
{
_a(*v);
_found = true;
_a(any_cast<Ts&>(_args[Idx])...);
throw stop_iteration();
}
catch (bad_any_cast) {}
}
Action _a;
any& _arg;
bool& _found;
std::array<any, N>& _args;
};
// recursion-free variadic version of for_each
template <class...>
struct for_each_variadic;
template <class Action>
struct dispatch
template <class F, class... Ts>
struct for_each_variadic<F,std::tuple<Ts...>>
{
dispatch(Action a, any* args, bool& found)
: _a(a), _args(args), _found(found) {}
template <class T>
__attribute__((always_inline))
auto get_next() const
{
bind_arg<Action, T> a(_a, *_args, _found);
return dispatch<bind_arg<Action, T>>(a, _args + 1, _found);
}
template <class T>
__attribute__((always_inline))
void operator()(T) const
void operator()(F f)
{
bind_arg<Action, T> a(_a, *_args, _found);
a();
auto call = [&](auto&& arg){f(std::forward<decltype(arg)>(arg)); return 0;};
(void) std::initializer_list<int> {call(Ts())...};
}
__attribute__((always_inline))
void operator()() const
{
_a();
}
Action _a;
any* _args;
bool& _found;
};
template <class F>
inline void for_each_pack(F)
{};
// convert mpl sequence to std::tuple
template <class T, class R>
struct to_tuple_imp;
template <class F, class T, class... Ts>
inline void for_each_pack(F f)
template <class... Ts, class X>
struct to_tuple_imp<std::tuple<Ts...>, X>
{
f(T());
for_each_pack<F, Ts...>(f);
typedef std::tuple<Ts..., X> type;
};
template <class F, class Seq, class Iter, class... Ts>
inline void for_each_alt(F f, Iter)
template <class Seq>
struct to_tuple
{
for_each_alt<F, Seq, typename next<Iter>::type, Ts...,
typename deref<Iter>::type>
(f, typename next<Iter>::type());
}
typedef typename mpl::fold<Seq, std::tuple<>,
to_tuple_imp<mpl::_1, mpl::_2>>::type type;
};
// nested type loops via variadic templates
template <class...>
struct inner_loop {};
template <class F, class Seq, class Iter, class... Ts>
inline void for_each_alt(F f, typename end<Seq>::type)
template <class Action, class... Ts>
struct inner_loop<Action, std::tuple<Ts...>>
{
for_each_pack<F, Ts...>(f);
}
inner_loop(Action a): _a(a) {}
template <class TR1, class... TRS, class Action>
void nested_for_each_imp(Action a);
template <class T>
__attribute__((always_inline))
void operator()(T) const { _a(Ts()..., T()); } // innermost loop
Action _a;
};
template <class Action, class... TRS>
struct inner_loop
template <class Action, class... Ts, class TR1, class... TRS>
struct inner_loop<Action, std::tuple<Ts...>, TR1, TRS...>
{
inner_loop(Action a): _a(a) {}
......@@ -160,33 +150,32 @@ struct inner_loop
__attribute__((always_inline))
void operator()(T) const
{
nested_for_each_imp<TRS...>(_a.template get_next<T>());
typedef inner_loop<Action, std::tuple<Ts..., T>, TRS...> inner_loop_t;
typedef typename to_tuple<TR1>::type tr_tuple;
for_each_variadic<inner_loop_t, tr_tuple>()(inner_loop_t(_a));
}
Action _a;
};
template <class TR1, class... TRS, class Action>
void nested_for_each_imp(Action a)
{
for_each_alt<inner_loop<Action, TRS...>,
TR1, typename begin<TR1>::type>
(inner_loop<Action, TRS...>(a), typename begin<TR1>::type());
}
template <class Action>
void nested_for_each_imp(Action a)
{
a();
}
// final function
template <class... TRS, class Action, class... Args>
template <class TR1, class... TRS, class Action, class... Args>
bool nested_for_each(Action a, Args... args)
{
bool found = false;
std::array<any, sizeof...(args)> as{{args...}};
auto b = dispatch<Action>(a, &as[0], found);
nested_for_each_imp<TRS...>(b);
return found;
auto b = all_any_cast<Action, sizeof...(args)>(a, as);
try
{
typedef decltype(b) action_t;
typedef typename to_tuple<TR1>::type tr_tuple;
typedef inner_loop<action_t, std::tuple<>, TRS...> inner_loop_t;
for_each_variadic<inner_loop_t, tr_tuple>()(inner_loop_t(b));
return false;
}
catch (stop_iteration&)
{
return true;
}
}
} // mpl namespace
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment