
* mln/core/internal/complex_iter_base.hh: New. * mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>): Remove. (mln::internal::complex_fwd_iter_<D>) (mln::internal::complex_bkd_iter_<D>): Inherit from mln::internal::complex_iter_base_. Adjust. * mln/core/faces_iter.hh (mln::internal::faces_iter_<N, D, E>): Remove. (mln::internal::faces_fwd_iter_<N, D>) (mln::internal::faces_bkd_iter_<N, D>): Inherit from mln::internal::complex_iter_base_. Adjust. * mln/core/face.hh (mln::face_handle<N, D>::n): New accessor. (mln::face_handle<N, D>::complex_type) (mln::any_face_handle<D>::complex_type): New typedefs. (mln::face_handle<N, D>::invalidate) (mln::any_face_handle<D>::invalidate): New methods. --- milena/ChangeLog | 25 +++ milena/mln/core/complex_iter.hh | 219 ++---------------------- milena/mln/core/face.hh | 35 ++++ milena/mln/core/faces_iter.hh | 215 ++---------------------- milena/mln/core/internal/complex_iter_base.hh | 214 ++++++++++++++++++++++++ 5 files changed, 310 insertions(+), 398 deletions(-) create mode 100644 milena/mln/core/internal/complex_iter_base.hh diff --git a/milena/ChangeLog b/milena/ChangeLog index f164de6..f4629b7 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,30 @@ 2008-09-12 Roland Levillain <roland@lrde.epita.fr> + Factor (more) iterators on complexes and faces. + + * mln/core/internal/complex_iter_base.hh: New. + * mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>): + Remove. + (mln::internal::complex_fwd_iter_<D>) + (mln::internal::complex_bkd_iter_<D>): + Inherit from mln::internal::complex_iter_base_. + Adjust. + * mln/core/faces_iter.hh (mln::internal::faces_iter_<N, D, E>): + Remove. + (mln::internal::faces_fwd_iter_<N, D>) + (mln::internal::faces_bkd_iter_<N, D>): + Inherit from mln::internal::complex_iter_base_. + Adjust. + * mln/core/face.hh (mln::face_handle<N, D>::n): New accessor. + (mln::face_handle<N, D>::complex_type) + (mln::any_face_handle<D>::complex_type): + New typedefs. + (mln::face_handle<N, D>::invalidate) + (mln::any_face_handle<D>::invalidate): + New methods. + +2008-09-12 Roland Levillain <roland@lrde.epita.fr> + Add iterators on the n-faces of a complex. * mln/core/faces_iter.hh: New. diff --git a/milena/mln/core/complex_iter.hh b/milena/mln/core/complex_iter.hh index 4aa9b99..3dcb445 100644 --- a/milena/mln/core/complex_iter.hh +++ b/milena/mln/core/complex_iter.hh @@ -31,95 +31,11 @@ /// \file mln/core/complex_iter.hh /// \brief Definition of forward and backward iterators on complexes. -# include <limits> - -# include <mln/core/concept/iterator.hh> -# include <mln/core/complex.hh> +# include <mln/core/internal/complex_iter_base.hh> namespace mln { - // Fwd decls. - template <unsigned D> class complex; - - /*--------------------------------. - | internal::complex_iter_<D, E>. | - `--------------------------------*/ - - namespace internal - { - /// \brief Factoring classe for iterators on all the faces of - /// a mln::complex<D>. - /// - /// \arg \p D The dimension of the complex this iterator belongs to. - /// \arg \p E The type exact type of the iterator. - template <unsigned D, typename E> - class complex_iter_ : public Iterator<E> - { - typedef complex_iter_<D, E> self_; - - public: - typedef any_face_handle<D> face; - - /// Construction and assignment. - /// \{ - complex_iter_(); - /* FIXME: Keep this non-const? See a (big) comment about this in - milena/tests/complex_image.cc. */ - complex_iter_(complex<D>& c); - complex_iter_(const self_& rhs); - self_& operator= (const self_& rhs); - /// \} - - /// Manipulation. - /// \{ - /// Test if the iterator is valid. - bool is_valid() const; - /// Invalidate the iterator. - void invalidate(); - /// \} - - /// Conversion and accessors. - /// \{ - /// Reference to the corresponding any-face handle. - const face& to_face () const; - /// Convert the iterator into an any-face handle. - operator face() const; - /// \} - - protected: - /// The face handle this iterator is pointing to. - face face_; - - private: - /// \brief An invalid value for both the dimension and the id of - /// the face. - /// - /// Use a function instead of a static constant, since `static' - /// variables needs to be compiled once, which requires a compiled - /// library to avoid duplicate symbols, which is something that - /// was not really planned in Milena. A function tagged `inlined' - /// can appear multiple times in a program, and solves this - /// problem. We rely on the compiler to inline this call. - /// - /// Of course, we could have used UINT_MAX, but it is not very - /// C++. - unsigned invalid_unsigned_() const; - }; - - - /* FIXME: This hand-made delegation is painful. We should rely on - the general mechanism provided by Point_Site. But then again, we - need to refine/adjust the interface of Point_Site w.r.t. the - mandatory conversions to points. */ - template <unsigned D, typename E> - inline - std::ostream& - operator<<(std::ostream& ostr, const complex_iter_<D, E>& p); - - } // end of mln::internal - - /*-----------------------. | complex_fwd_iter_<D>. | `-----------------------*/ @@ -129,10 +45,15 @@ namespace mln /// \arg \p D The dimension of the complex this iterator belongs to. template <unsigned D> class complex_fwd_iter_ - : public internal::complex_iter_< D, complex_fwd_iter_<D> > + : public internal::complex_iter_base_< any_face_handle<D>, + complex_fwd_iter_<D> > { + public: + typedef any_face_handle<D> face; + + private: typedef complex_fwd_iter_<D> self_; - typedef internal::complex_iter_< D, self_ > super_; + typedef internal::complex_iter_base_< face, self_ > super_; public: using super_::is_valid; @@ -142,7 +63,7 @@ namespace mln /// Construction and assignment. /// \{ complex_fwd_iter_(); - // FIXME: See above (internal::complex_iter_'s default ctor). + // FIXME: See above (internal::complex_iter_base_'s default ctor). complex_fwd_iter_(complex<D>& c); complex_fwd_iter_(const self_& rhs); self_& operator= (const self_& rhs); @@ -174,10 +95,15 @@ namespace mln /// \arg \p D The dimension of the complex this iterator belongs to. template <unsigned D> class complex_bkd_iter_ - : public internal::complex_iter_< D, complex_bkd_iter_<D> > + : public internal::complex_iter_base_< any_face_handle<D>, + complex_bkd_iter_<D> > { + public: + typedef any_face_handle<D> face; + + private: typedef complex_bkd_iter_<D> self_; - typedef internal::complex_iter_< D, self_ > super_; + typedef internal::complex_iter_base_< face, self_ > super_; public: using super_::is_valid; @@ -187,7 +113,7 @@ namespace mln /// Construction and assignment. /// \{ complex_bkd_iter_(); - // FIXME: See above (internal::complex_iter_'s default ctor). + // FIXME: See above (internal::complex_iter_base_'s default ctor). complex_bkd_iter_(complex<D>& c); complex_bkd_iter_(const self_& rhs); self_& operator= (const self_& rhs); @@ -213,113 +139,6 @@ namespace mln # ifndef MLN_INCLUDE_ONLY - /*--------------------------------. - | internal::complex_iter_<D, E>. | - `--------------------------------*/ - - namespace internal - { - - template <unsigned D, typename E> - inline - complex_iter_<D, E>::complex_iter_() - { - // Invalidate face_. - invalidate(); - } - - template <unsigned D, typename E> - inline - complex_iter_<D, E>::complex_iter_(complex<D>& c) - { - face_.set_cplx(c); - // Invalidate face_. - invalidate(); - } - - template <unsigned D, typename E> - inline - complex_iter_<D, E>::complex_iter_(const complex_iter_<D, E>& rhs) - : face_(rhs.face_) - { - } - - template <unsigned D, typename E> - inline - complex_iter_<D, E>& - complex_iter_<D, E>::operator=(const complex_iter_<D, E>& rhs) - { - if (&rhs == this) - return *this; - face_ = rhs.face_; - return *this; - } - - template <unsigned D, typename E> - inline - bool - complex_iter_<D, E>::is_valid() const - { - return face_.is_valid(); - } - - template <unsigned D, typename E> - inline - void - complex_iter_<D, E>::invalidate() - { - face_.set_n(invalid_unsigned_()); - face_.set_face_id(invalid_unsigned_()); - } - - template <unsigned D, typename E> - inline - const any_face_handle<D>& - complex_iter_<D, E>::to_face() const - { - return face_; - } - - template <unsigned D, typename E> - inline - complex_iter_<D, E>::operator any_face_handle<D>() const - { - mln_precondition(is_valid()); - return face_; - } - - template <unsigned D, typename E> - unsigned - complex_iter_<D, E>::invalid_unsigned_() const - { - return std::numeric_limits<unsigned>::max(); - } - - template <unsigned D, typename E> - inline - std::ostream& - operator<<(std::ostream& ostr, const complex_iter_<D, E>& p) - { - /* FIXME: We should use p.to_face() here, but as it lacks the - precondition the conversion operator has, so we use the latter. - - We should - - rename `to_face' as `to_face_'; - - write a new `to_face' routine checking the validity of the - iterator; - - have the conversion operator to face use this new `to_face' - routine; - - adjust former clients of `to_face' - - This is a general remark that applies to all iterators of - Milena. */ - any_face_handle<D> f = p; - return ostr << "(dim = " << f.n() << ", id = " << f.face_id() << ')'; - } - - } // end of mln::internal - - /*-----------------------. | complex_fwd_iter_<D>. | `-----------------------*/ @@ -334,6 +153,7 @@ namespace mln template <unsigned D> inline complex_fwd_iter_<D>::complex_fwd_iter_(complex<D>& c) + : super_(c) { set_cplx(c); mln_postcondition(!is_valid()); @@ -413,8 +233,6 @@ namespace mln | complex_bkd_iter_<D>. | `-----------------------*/ - // FIXME: Resume here. - template <unsigned D> inline complex_bkd_iter_<D>::complex_bkd_iter_() @@ -425,6 +243,7 @@ namespace mln template <unsigned D> inline complex_bkd_iter_<D>::complex_bkd_iter_(complex<D>& c) + : super_(c) { set_cplx(c); mln_postcondition(!is_valid()); diff --git a/milena/mln/core/face.hh b/milena/mln/core/face.hh index 4e8e958..9fd685a 100644 --- a/milena/mln/core/face.hh +++ b/milena/mln/core/face.hh @@ -143,6 +143,9 @@ namespace mln template <unsigned N, unsigned D> struct face_handle { + // The type of the complex this handle points to. + typedef complex<D> complex_type; + /// Build a non-initialized face handle. face_handle(); /// Build a face handle from \a complex and \a face_id. @@ -156,6 +159,8 @@ namespace mln /// Is this handle valid? bool is_valid() const; + /// Invalidate this handle. + void invalidate(); /// Accessors. /// \{ @@ -167,6 +172,9 @@ namespace mln /// Set the complex the face belongs to. void set_cplx(complex<D>& cplx); + /// Return the dimension of the face. + // FIXME: Rename as `dim'? + unsigned n() const; /// Set the id of the face. void set_face_id(unsigned face_id); @@ -259,6 +267,9 @@ namespace mln template <unsigned D> struct any_face_handle { + // The type of the complex this handle points to. + typedef complex<D> complex_type; + /// Build a non-initialized face handle. any_face_handle(); /// Build a face handle from \a complex and \a face_id. @@ -276,6 +287,8 @@ namespace mln /// Is this handle valid? bool is_valid() const; + /// Invalidate this handle. + void invalidate(); /// Accessors. /// \{ @@ -411,6 +424,13 @@ namespace mln } template <unsigned N, unsigned D> + void + face_handle<N, D>::invalidate() + { + set_face_id(std::numeric_limits<unsigned>::max()); + } + + template <unsigned N, unsigned D> complex<D>& face_handle<N, D>::cplx() const { @@ -420,6 +440,13 @@ namespace mln template <unsigned N, unsigned D> unsigned + face_handle<N, D>::n() const + { + return N; + } + + template <unsigned N, unsigned D> + unsigned face_handle<N, D>::face_id() const { return face_id_; @@ -574,6 +601,14 @@ namespace mln } template <unsigned D> + void + any_face_handle<D>::invalidate() + { + set_n(std::numeric_limits<unsigned>::max()); + set_face_id(std::numeric_limits<unsigned>::max()); + } + + template <unsigned D> complex<D>& any_face_handle<D>::cplx() const { diff --git a/milena/mln/core/faces_iter.hh b/milena/mln/core/faces_iter.hh index 25dd2c2..e11073d 100644 --- a/milena/mln/core/faces_iter.hh +++ b/milena/mln/core/faces_iter.hh @@ -32,99 +32,11 @@ /// \brief Definition of forward and backward iterators on the n-faces /// of a complex. -# include <limits> - -# include <mln/core/concept/iterator.hh> -# include <mln/core/complex.hh> +# include <mln/core/internal/complex_iter_base.hh> namespace mln { - // Fwd decls. - template <unsigned D> class complex; - - /*---------------------------------. - | internal::faces_iter_<N, D, E>. | - `---------------------------------*/ - - // FIXME: Maybe we should have a `face' parameter instead of N & D. - // This way, we could merge this class and - // internal::complex_iter_x<D, E>. - - namespace internal - { - /// \brief Factoring classe for iterators on all the \p N-faces of - /// a mln::complex<D>. - /// - /// \arg \p N The dimension of the face associated to this iterator. - /// \arg \p D The dimension of the complex this iterator belongs to. - /// \arg \p E The type exact type of the iterator. - template <unsigned N, unsigned D, typename E> - class faces_iter_ : public Iterator<E> - { - typedef faces_iter_<N, D, E> self_; - - public: - typedef face_handle<N, D> face; - - /// Construction and assignment. - /// \{ - /* FIXME: Keep this non-const? See a (big) comment about this in - milena/tests/complex_image.cc. */ - faces_iter_(complex<D>& c); - faces_iter_(const self_& rhs); - self_& operator= (const self_& rhs); - /// \} - - /// Manipulation. - /// \{ - /// Test if the iterator is valid. - bool is_valid() const; - /// Invalidate the iterator. - void invalidate(); - /// \} - - /// Conversion and accessors. - /// \{ - /// Reference to the corresponding face handle. - const face& to_face () const; - /// Convert the iterator into an face handle. - operator face() const; - /// \} - - protected: - /// The face handle this iterator is pointing to. - face face_; - - private: - /// \brief An invalid value for both the dimension and the id of - /// the face. - /// - /// Use a function instead of a static constant, since `static' - /// variables needs to be compiled once, which requires a compiled - /// library to avoid duplicate symbols, which is something that - /// was not really planned in Milena. A function tagged `inlined' - /// can appear multiple times in a program, and solves this - /// problem. We rely on the compiler to inline this call. - /// - /// Of course, we could have used UINT_MAX, but it is not very - /// C++. - unsigned invalid_unsigned_() const; - }; - - - /* FIXME: This hand-made delegation is painful. We should rely on - the general mechanism provided by Point_Site. But then again, we - need to refine/adjust the interface of Point_Site w.r.t. the - mandatory conversions to points. */ - template <unsigned N, unsigned D, typename E> - inline - std::ostream& - operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p); - - } // end of mln::internal - - /*------------------------. | faces_fwd_iter_<N, D>. | `------------------------*/ @@ -135,10 +47,15 @@ namespace mln /// \arg \p D The dimension of the complex this iterator belongs to. template <unsigned N, unsigned D> class faces_fwd_iter_ - : public internal::faces_iter_< N, D, faces_fwd_iter_<N, D> > + : public internal::complex_iter_base_< face_handle<N, D>, + faces_fwd_iter_<N, D> > { + public: + typedef face_handle<N, D> face; + + private: typedef faces_fwd_iter_<N, D> self_; - typedef internal::faces_iter_< N, D, self_ > super_; + typedef internal::complex_iter_base_< face, self_ > super_; public: using super_::is_valid; @@ -147,7 +64,7 @@ namespace mln public: /// Construction and assignment. /// \{ - // FIXME: See above (internal::faces_iter_'s default ctor). + // FIXME: See above (internal::complex_iter_base_'s default ctor). faces_fwd_iter_(complex<D>& c); faces_fwd_iter_(const self_& rhs); self_& operator= (const self_& rhs); @@ -176,10 +93,15 @@ namespace mln /// \arg \p D The dimension of the complex this iterator belongs to. template <unsigned N, unsigned D> class faces_bkd_iter_ - : public internal::faces_iter_< N, D, faces_bkd_iter_<N, D> > + : public internal::complex_iter_base_< face_handle<N, D>, + faces_bkd_iter_<N, D> > { + public: + typedef face_handle<N, D> face; + + private: typedef faces_bkd_iter_<N, D> self_; - typedef internal::faces_iter_< N, D, self_ > super_; + typedef internal::complex_iter_base_< face, self_ > super_; public: using super_::is_valid; @@ -188,7 +110,7 @@ namespace mln public: /// Construction and assignment. /// \{ - // FIXME: See above (internal::faces_iter_'s default ctor). + // FIXME: See above (internal::complex_iter_base_'s default ctor). faces_bkd_iter_(complex<D>& c); faces_bkd_iter_(const self_& rhs); self_& operator= (const self_& rhs); @@ -210,109 +132,6 @@ namespace mln # ifndef MLN_INCLUDE_ONLY - /*---------------------------------. - | internal::faces_iter_<N, D, E>. | - `---------------------------------*/ - - namespace internal - { - - template <unsigned N, unsigned D, typename E> - inline - faces_iter_<N, D, E>::faces_iter_(complex<D>& c) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - - face_.set_cplx(c); - // Invalidate face_. - invalidate(); - } - - template <unsigned N, unsigned D, typename E> - inline - faces_iter_<N, D, E>::faces_iter_(const faces_iter_<N, D, E>& rhs) - : face_(rhs.face_) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - } - - template <unsigned N, unsigned D, typename E> - inline - faces_iter_<N, D, E>& - faces_iter_<N, D, E>::operator=(const faces_iter_<N, D, E>& rhs) - { - if (&rhs == this) - return *this; - face_ = rhs.face_; - return *this; - } - - template <unsigned N, unsigned D, typename E> - inline - bool - faces_iter_<N, D, E>::is_valid() const - { - return face_.is_valid(); - } - - template <unsigned N, unsigned D, typename E> - inline - void - faces_iter_<N, D, E>::invalidate() - { - face_.set_face_id(invalid_unsigned_()); - } - - template <unsigned N, unsigned D, typename E> - inline - const face_handle<N, D>& - faces_iter_<N, D, E>::to_face() const - { - return face_; - } - - template <unsigned N, unsigned D, typename E> - inline - faces_iter_<N, D, E>::operator face_handle<N, D>() const - { - mln_precondition(is_valid()); - return face_; - } - - template <unsigned N, unsigned D, typename E> - unsigned - faces_iter_<N, D, E>::invalid_unsigned_() const - { - return std::numeric_limits<unsigned>::max(); - } - - template <unsigned N, unsigned D, typename E> - inline - std::ostream& - operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p) - { - /* FIXME: We should use p.to_face() here, but as it lacks the - precondition the conversion operator has, so we use the latter. - - We should - - rename `to_face' as `to_face_'; - - write a new `to_face' routine checking the validity of the - iterator; - - have the conversion operator to face use this new `to_face' - routine; - - adjust former clients of `to_face' - - This is a general remark that applies to all iterators of - Milena. */ - typename faces_iter_<N, D, E>::face f = p; - return ostr << "(dim = " << N << ", id = " << f.face_id() << ')'; - } - - } // end of mln::internal - - /*------------------------. | faces_fwd_iter_<N, D>. | `------------------------*/ diff --git a/milena/mln/core/internal/complex_iter_base.hh b/milena/mln/core/internal/complex_iter_base.hh new file mode 100644 index 0000000..df9b39a --- /dev/null +++ b/milena/mln/core/internal/complex_iter_base.hh @@ -0,0 +1,214 @@ +// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH +# define MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH + +/// \file mln/core/complex_iter_base.hh +/// \brief Definition of an implementation (factoring) class for +/// iterators on complexes. + +# include <limits> + +# include <mln/metal/equal.hh> + +# include <mln/core/concept/iterator.hh> +# include <mln/core/complex.hh> + +namespace mln +{ + + // Forward declaration. + template <unsigned D> class complex; + + namespace internal + { + /// \brief Factoring classe for iterators on complexes. + /// + /// \arg \p F The type of the face handle. + /// \arg \p E The type exact type of the iterator. + template <typename F, typename E> + class complex_iter_base_ : public Iterator<E> + { + typedef complex_iter_base_<F, E> self_; + + public: + typedef F face; + typedef typename F::complex_type complex_type; + + /// Construction and assignment. + /// \{ + /* FIXME: Keep this non-const? See a (big) comment about this in + milena/tests/complex_image.cc. */ + complex_iter_base_(); + complex_iter_base_(complex_type& c); + complex_iter_base_(const self_& rhs); + self_& operator= (const self_& rhs); + /// \} + + /// Manipulation. + /// \{ + /// Test if the iterator is valid. + bool is_valid() const; + /// Invalidate the iterator. + void invalidate(); + /// \} + + /// Conversion and accessors. + /// \{ + /// Reference to the corresponding face handle. + const face& to_face () const; + /// Convert the iterator into an face handle. + operator face() const; + /// \} + + protected: + /// The face handle this iterator is pointing to. + face face_; + }; + + + /* FIXME: This hand-made delegation is painful. We should rely on + the general mechanism provided by Point_Site. But then again, we + need to refine/adjust the interface of Point_Site w.r.t. the + mandatory conversions to points. */ + template <typename F, typename E> + inline + std::ostream& + operator<<(std::ostream& ostr, const complex_iter_base_<F, E>& p); + + } // end of mln::internal + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + template <typename F, typename E> + inline + complex_iter_base_<F, E>::complex_iter_base_() + { + // Ensure F and E are compatible. + mlc_equal(F, typename E::face)::check(); + + invalidate(); + } + + template <typename F, typename E> + inline + complex_iter_base_<F, E>::complex_iter_base_(complex_type& c) + { + // Ensure F and E are compatible. + mlc_equal(F, typename E::face)::check(); + + face_.set_cplx(c); + // Invalidate face_. + invalidate(); + } + + template <typename F, typename E> + inline + complex_iter_base_<F, E>::complex_iter_base_(const complex_iter_base_<F, E>& rhs) + : face_(rhs.face_) + { + // Ensure F and E are compatible. + mlc_equal(F, typename E::face)::check(); + } + + template <typename F, typename E> + inline + complex_iter_base_<F, E>& + complex_iter_base_<F, E>::operator=(const complex_iter_base_<F, E>& rhs) + { + if (&rhs == this) + return *this; + face_ = rhs.face_; + return *this; + } + + template <typename F, typename E> + inline + bool + complex_iter_base_<F, E>::is_valid() const + { + return face_.is_valid(); + } + + template <typename F, typename E> + inline + void + complex_iter_base_<F, E>::invalidate() + { + face_.invalidate(); + } + + template <typename F, typename E> + inline + const F& + complex_iter_base_<F, E>::to_face() const + { + return face_; + } + + template <typename F, typename E> + inline + complex_iter_base_<F, E>::operator F() const + { + mln_precondition(is_valid()); + return face_; + } + + + template <typename F, typename E> + inline + std::ostream& + operator<<(std::ostream& ostr, const complex_iter_base_<F, E>& p) + { + /* FIXME: We should use p.to_face() here, but as it lacks the + precondition the conversion operator has, so we use the latter. + + We should + - rename `to_face' as `to_face_'; + - write a new `to_face' routine checking the validity of the + iterator; + - have the conversion operator to face use this new `to_face' + routine; + - adjust former clients of `to_face' + + This is a general remark that applies to all iterators of + Milena. */ + F f = p; + return ostr << "(dim = " << f.n() << ", id = " << f.face_id() << ')'; + } + + } // end of mln::internal + +# endif // ! MLN_INCLUDE_ONLY + +} // end of mln + +#endif // ! MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH -- 1.6.0.1