
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Equip proxies to transparently handle operators. * doc/tutorial/examples/p_array.cc: Add tests on proxy_level and on op== applied on proxies. * mln/core/concept/proxy.hh (internal): New meta-code. (set_binary_, set_unary_): Re-activate and make it work. (operator==): New; it is only a start. (operator-): Likewise. (proxy_level): New in Proxy requirements. (helper_proxy_impl): Define proxy_level. * mln/core/concept/gpoint.hh: . doc/tutorial/examples/p_array.cc | 28 +++++++- mln/core/concept/gpoint.hh | 2 mln/core/concept/proxy.hh | 129 ++++++++++++++++++++++++++++++++++----- 3 files changed, 142 insertions(+), 17 deletions(-) Index: doc/tutorial/examples/p_array.cc --- doc/tutorial/examples/p_array.cc (revision 2030) +++ doc/tutorial/examples/p_array.cc (working copy) @@ -27,6 +27,15 @@ using namespace mln; typedef p_array<point2d> Arr1; + typedef p_array<mln_psite_(Arr1)> Arr2; + + { + mln_assertion(mln_psite_(Arr1)::proxy_level == 1); + mln_assertion(mln_piter_(Arr1)::proxy_level == 2); + mln_assertion(mln_psite_(Arr2)::proxy_level == 2); + mln_assertion(mln_piter_(Arr2)::proxy_level == 3); + } + Arr1 arr1; { @@ -41,22 +50,26 @@ } { - typedef p_array< mln_psite_(Arr1) > Arr2; + Arr2 arr2; + // Fill arr2 from arr1 contents. + { mln_piter_(Arr1) p(arr1); for_all(p) if (p.row() % 2 && p.col() % 2) arr2.append(p); + } std::cout << "arr2 = " << arr2 << std::endl; picture(arr2); + // Display indices. { mln_piter_(Arr2) p(arr2); for_all(p) { -// mln_assertion(make::point2d(p.row(), p.col()) == p); // FIXME: Make it work. + mln_assertion(make::point2d(p.row(), p.col()) == p); std::cout << "point " << p << ": #" << index_of_in(p, arr2) << " in arr2, #" << index_of_in(p, arr1) << " in arr1" << std::endl; @@ -64,6 +77,17 @@ } mln_invariant(arr2 < arr1); + + { + mln_piter_(Arr1) p1(arr1); + mln_piter_(Arr2) p2(arr2); + for_all_2(p1, p2) + { + mln_assertion(p2 == p1); // same as: p2.to_site() == p1.to_site() + p1.next(); // p1 goes twice fast as p2. + } + } + } } Index: mln/core/concept/proxy.hh --- mln/core/concept/proxy.hh (revision 2030) +++ mln/core/concept/proxy.hh (working copy) @@ -46,40 +46,75 @@ template <typename E> struct Proxy; - /* - FIXME: Re-activate. + namespace internal + { - namespace trait + template <bool b, typename P> struct unproxy_if; + + template <typename P> + struct unproxy_if< true, P > + { + typedef mln_subject(P) ret; + static typename P::q_subject on(const Proxy<P>& p) { return exact(p).unproxy(); } + }; + + template <typename P> + struct unproxy_if< false, P > { + typedef P ret; + static const P& on(const Proxy<P>& p) { return exact(p); } + }; + + template <typename L, typename R> + struct unproxy_couple + { + enum { L_level = L::proxy_level, + R_level = R::proxy_level }; // To prevent a weird g++ warning. + typedef internal::unproxy_if<(L_level >= R_level), L> L_helper; + typedef internal::unproxy_if<(R_level >= L_level), R> R_helper; + typedef typename L_helper::ret L_ret; + typedef typename R_helper::ret R_ret; + }; - template < typename Op, typename P1, typename P2 > - struct set_binary_< Op, mln::Proxy, P1, mln::Proxy, P2 > + } // end of namespace mln::internal + + + + namespace trait { - typedef mln_trait_binary(Op, mln_subject(P1), mln_subject(P2)) ret; + + template < template <class, class> class Op, + typename L, typename R > + struct set_binary_< Op, mln::Proxy, L, mln::Proxy, R > + { + typedef mln::internal::unproxy_couple<L, R> helper; + typedef mln_trait_binary(Op, + typename helper::L_ret, + typename helper::R_ret) ret; }; - template < typename Op, typename P, typename O > + template < template <class, class> class Op, + typename P, typename O > struct set_binary_< Op, mln::Proxy, P, mln::Object, O > { typedef mln_trait_binary(Op, mln_subject(P), O) ret; }; - template < typename Op, typename E, typename P > - struct set_binary_< Op, mln::Object, E, mln::Proxy, P > + template < template <class, class> class Op, + typename O, typename P > + struct set_binary_< Op, mln::Object, O, mln::Proxy, P > { typedef mln_trait_binary(Op, O, mln_subject(P)) ret; }; - template < typename Op, typename P > - struct set_binary_< Op, mln::Proxy, P > + template < template <class> class Op, typename P > + struct set_unary_< Op, mln::Proxy, P > { typedef mln_trait_unary(Op, mln_subject(P)) ret; }; } // end of namespace mln::trait - */ - /// Proxy category flag type. @@ -99,6 +134,7 @@ typedef Proxy<void> category; /* + enum { proxy_level }; typedef subject; typedef q_subject; q_subject unproxy() const; @@ -113,6 +149,63 @@ }; + + template <typename L, typename R> + inline + mln_trait_op_minus(L, R) + operator-(const mln::Proxy<L>& lhs, const mln::Proxy<R>& rhs) + { + typedef typename internal::unproxy_couple<L, R>::L_helper L_unproxy; + typedef typename internal::unproxy_couple<L, R>::R_helper R_unproxy; + return L_unproxy::on(lhs) - R_unproxy::on(rhs); + } + + template <typename P, typename O> + inline + mln_trait_op_minus(P, O) + operator-(const Proxy<P>& p, const Object<O>& o) + { + return exact(p).unproxy() - exact(o); + } + + template <typename O, typename P> + inline + mln_trait_op_minus(O, P) + operator-(const Object<O>& o, const Proxy<P>& p) + { + return exact(o) - exact(p).unproxy(); + } + + + + template <typename L, typename R> + inline + mln_trait_op_eq(L, R) + operator==(const mln::Proxy<L>& lhs, const mln::Proxy<R>& rhs) + { + typedef typename internal::unproxy_couple<L, R>::L_helper L_unproxy; + typedef typename internal::unproxy_couple<L, R>::R_helper R_unproxy; + return L_unproxy::on(lhs) == R_unproxy::on(rhs); + } + + template <typename P, typename O> + inline + mln_trait_op_eq(P, O) + operator==(const Proxy<P>& p, const Object<O>& o) + { + return exact(p).unproxy() == exact(o); + } + + template <typename O, typename P> + inline + mln_trait_op_eq(O, P) + operator==(const Object<O>& o, const Proxy<P>& p) + { + return exact(o) == exact(p).unproxy(); + } + + + namespace internal { @@ -181,11 +274,15 @@ template <typename Subject, typename E, bool rec = true> struct helper_proxy_impl : proxy_impl< mln_subject(Subject), E > // Rec. - {}; + { + enum { proxy_level = Subject::proxy_level + 1}; + }; template <typename Subject, typename E> struct helper_proxy_impl< Subject, E, false > // Stop rec. - {}; + { + enum { proxy_level = 1 }; + }; template <typename Subject, typename E> struct proxy_impl : helper_proxy_impl< Subject, E, @@ -224,6 +321,8 @@ inline Proxy<E>::Proxy() { + enum { proxy_level = E::proxy_level }; // FIXME: Check that it is >= 0... + typedef mln_subject(E) subject; typedef typename E::q_subject q_subject; Index: mln/core/concept/gpoint.hh --- mln/core/concept/gpoint.hh (revision 2030) +++ mln/core/concept/gpoint.hh (working copy) @@ -92,6 +92,8 @@ template <typename E> struct Gpoint : public Object<E> { + typedef Gpoint<void> category; + /* typedef grid; typedef delta;