$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
complex.hh
1 // Copyright (C) 2008, 2009, 2010, 2012 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_TOPO_COMPLEX_HH
28 # define MLN_TOPO_COMPLEX_HH
29 
36 
37 # include <cstddef>
38 
39 # include <iosfwd>
40 
41 # include <mln/metal/bool.hh>
42 
43 # include <mln/util/tracked_ptr.hh>
44 
45 # include <mln/topo/face_data.hh>
46 # include <mln/topo/algebraic_face.hh>
47 # include <mln/topo/algebraic_n_face.hh>
48 # include <mln/topo/n_faces_set.hh>
49 
50 # include <mln/topo/complex_iterators.hh>
51 
52 
53 namespace mln
54 {
55 
56  namespace topo
57  {
58 
59  // Forward declarations (external).
60  template <unsigned N, unsigned D> class n_faces_set;
61  template <unsigned D> class face_fwd_iter;
62  template <unsigned D> class face_bkd_iter;
63 // FIXME: Disabled (moved to the attic).
64 # if 0
65  template <unsigned N, unsigned D> class faces_fwd_iter_;
66  template <unsigned N, unsigned D> class faces_bkd_iter_;
67 #endif
68 
69  // Forward declarations (internal).
70  namespace internal
71  {
72  template <unsigned D>
73  struct complex_data;
74 
75  template <unsigned N, unsigned D>
76  struct faces_set_mixin;
77  }
78 
79 
80  /*----------.
81  | Complex. |
82  `----------*/
83 
87  template <unsigned D>
88  class complex
89  {
90  public:
95 
96 // FIXME: Disabled (moved to the attic).
97 # if 0
98 
99  template <unsigned N>
100  struct fwd_fiter { typedef faces_fwd_iter_<N, D> ret; };
102  template <unsigned N>
103  struct bkd_fiter { typedef faces_bkd_iter_<N, D> ret; };
104 #endif
105 
109  complex();
110 
112  n_face<0, D> add_face();
113 
118  template <unsigned N>
119  n_face<N + 1, D> add_face(const n_faces_set<N, D>& adjacent_faces);
121 
128  unsigned nfaces() const;
129 
131  template <unsigned N>
132  unsigned nfaces_of_static_dim() const;
134 
145  unsigned nfaces_of_dim(unsigned n) const;
147 
151  void print(std::ostream& ostr) const;
153  template <unsigned N>
154  void print_faces(std::ostream& ostr) const;
156 
161  const void* addr() const;
162 
163  private:
166 
167  template <unsigned D_>
168  friend bool operator==(const complex<D_>& lhs, const complex<D_>& rhs);
169 
172  template <unsigned N, unsigned D_> friend class n_face;
173  template <unsigned D_> friend class face;
174 
175  template <unsigned N>
176  face_data<N, D>& face_data_(unsigned face_id);
177 
178  template <unsigned N>
179  const face_data<N, D>& face_data_(unsigned face_id) const;
181 
184  /* FIXME: Use something more constraining than the STL's
185  UnaryFunction/BinaryFunction. Use Function or Function_v2v?
186  Or a new subclass of Function? */
187 
188  /* FIXME: Replace F and ACCU by a Milena accumulator? */
189 
199  template <typename BinaryFunction, typename T>
200  T fold_left_(const BinaryFunction& f, const T& accu) const;
201 
203  template <typename UnaryFunction>
204  typename UnaryFunction::result_type
205  apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
207 
214  template <unsigned N>
215  void connect_(const algebraic_n_face<N, D>& f1,
216  const n_face<N + 1, D>& f2);
217  };
218 
219 
221  template <unsigned D>
222  bool
223  operator==(const complex<D>& lhs, const complex<D>& rhs);
224 
225 
227  template <unsigned D>
228  std::ostream&
229  operator<<(std::ostream& ostr, const complex<D>& c);
230 
231 
232  /*---------------.
233  | Complex data. |
234  `---------------*/
235 
290  /*---------------------.
291  | Faces of a complex. |
292  `---------------------*/
293 
296  namespace internal
297  {
298 
299  // Forward declarations.
300  template <unsigned N, unsigned D> struct lower_dim_faces_set_mixin;
301  template <unsigned N, unsigned D> struct higher_dim_faces_set_mixin;
302 
303  // -------------------------------------- //
304  // mln::topo::internal::faces_set_mixin. //
305  // -------------------------------------- //
306 
309 
310  template <unsigned N, unsigned D> struct faces_set_mixin;
311 
312 
317  template <unsigned N, unsigned D>
318  struct faces_set_mixin : public faces_set_mixin<N - 1, D>,
319  public lower_dim_faces_set_mixin<N, D>,
320  public higher_dim_faces_set_mixin<N, D>
321  {
322  std::vector< face_data<N, D> > faces_;
323 
327  void print(std::ostream& ostr) const;
330  void print_rec_asc(std::ostream& ostr) const;
332 
337  template <typename BinaryFunction, typename T>
338  T fold_left_(const BinaryFunction& f, const T& accu) const;
341  template <typename UnaryFunction>
342  typename UnaryFunction::result_type
343  apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
345  };
346 
351  template <unsigned D>
352  struct faces_set_mixin<D, D> : public faces_set_mixin<D - 1, D>,
353  public lower_dim_faces_set_mixin<D, D>
354  {
355  std::vector< face_data<D, D> > faces_;
356 
360  void print(std::ostream& ostr) const;
361  void print_rec_asc(std::ostream& ostr) const;
363 
368  template <typename BinaryFunction, typename T>
369  T fold_left_(const BinaryFunction& f, const T& accu) const;
372  template <typename UnaryFunction>
373  typename UnaryFunction::result_type
374  apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
376  };
377 
382  template <unsigned D>
383  struct faces_set_mixin<0, D> : public higher_dim_faces_set_mixin<0, D>
384  {
385  std::vector< face_data<0, D> > faces_;
386 
390  void print(std::ostream& ostr) const;
391  void print_rec_asc(std::ostream& ostr) const;
393 
398  template <typename BinaryFunction, typename T>
399  T fold_left_(const BinaryFunction& f, const T& accu) const;
402  template <typename UnaryFunction>
403  typename UnaryFunction::result_type
404  apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
406  };
407 
412  template <>
413  struct faces_set_mixin<0, 0>
414  {
415  std::vector< face_data<0, 0> > faces_;
416 
420  void print(std::ostream& ostr) const;
421  void print_rec_asc(std::ostream& ostr) const;
423 
428  template <typename BinaryFunction, typename T>
429  T fold_left_(const BinaryFunction& f, const T& accu) const;
432  template <typename UnaryFunction>
433  typename UnaryFunction::result_type
434  apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const;
436  };
438 
439 
440  // Tech note: g++-2.95 highly prefers to have the complex_data
441  // class to be defined after the specializations of
442  // 'faces_set_mixin'.
443 
448  template <unsigned D>
449  struct complex_data : public faces_set_mixin<D, D>
450  {
451  // Data is contained in super classes.
452  };
453 
454 
455  // ------------------------------------------------- //
456  // mln::topo::internal::lower_dim_faces_set_mixin. //
457  // mln::topo::internal::higher_dim_faces_set_mixin. //
458  // ------------------------------------------------- //
459 
462  template <unsigned N, unsigned D>
464  {
465  void print(std::ostream& ostr, const face_data<N, D>& f) const;
466  };
467 
468  template <unsigned N, unsigned D>
470  {
471  void print(std::ostream& ostr, const face_data<N, D>& f) const;
472  };
474 
475  } // end of namespace mln::topo::internal
476 
477 
478 
479 # ifndef MLN_INCLUDE_ONLY
480 
481  /*-----------------------.
482  | Complex construction. |
483  `-----------------------*/
484 
485  template <unsigned D>
486  inline
488  // Allocate data for this complex.
489  : data_(new internal::complex_data<D>())
490  {
491  }
492 
493  template <unsigned D>
494  inline
495  n_face<0, D>
496  complex<D>::add_face()
497  {
498  // Upcast `data_' to get access to the field `faces_' of its
499  // base class `internal::faces_set_mixin<0, D>'.
500  std::vector< face_data<0, D> >& faces_0 =
501  static_cast< internal::faces_set_mixin<0, D>& >(*data_).faces_;
502  /* FIXME: This is not thread-proof (these two lines should
503  form an atomic section). */
504  faces_0.push_back(face_data<0, D>());
505  unsigned id = nfaces_of_static_dim<0>() - 1;
506  return n_face<0, D>(*this, id);
507  }
508 
509  template <unsigned D>
510  template <unsigned N>
511  inline
512  n_face<N + 1, D>
513  complex<D>::add_face(const n_faces_set<N, D>& adjacent_faces)
514  {
515  typedef typename std::vector< algebraic_n_face<N, D> >::const_iterator
516  iter_t;
517 
518  // Ensure ADJACENT_FACES are already part of the complex.
519  if (!HAS_NDEBUG)
520  for (iter_t a = adjacent_faces.faces().begin();
521  a != adjacent_faces.faces().end(); ++a)
522  {
523  mln_precondition(a->cplx() == *this);
524  mln_precondition(a->is_valid());
525  }
526 
527  face_data<N + 1, D> f;
528  // Upcast `data_' to get access to the field `faces_' of its
529  // base class `internal::faces_set_mixin<N + 1, D>'.
530  std::vector< face_data<N + 1, D> >& faces_n_plus_1 =
531  static_cast< internal::faces_set_mixin<N + 1, D>& >(*data_).faces_;
532  /* FIXME: This is not thread-proof (these two lines should
533  form an atomic section). */
534  faces_n_plus_1.push_back(f);
535  unsigned id = nfaces_of_static_dim<N + 1>() - 1;
536 
537  n_face<N + 1, D> fh(*this, id);
538  // Connect F and its ADJACENT_FACES.
539  for (iter_t a = adjacent_faces.faces().begin();
540  a != adjacent_faces.faces().end(); ++a)
541  /* Connect
542  - algebraic n-face *A,
543  - and an (n+1)-algebraic face based on FH and having the
544  sign of *A. */
545  connect_(*a, fh);
546  return fh;
547  }
548 
549 
550  /*-------.
551  | Misc. |
552  `-------*/
553 
554  namespace internal
555  {
556 
568  struct add_size
569  {
570  template <typename T, typename Container>
571  T operator()(const T& x, const Container& c) const
572  {
573  return x + c.size();
574  }
575  };
576 
588  struct get_size
589  {
590  typedef std::size_t result_type;
591 
592  template <typename Container>
593  typename Container::size_type operator()(const Container& c) const
594  {
595  return c.size();
596  }
597  };
598 
599  } // end of namespace mln::topo::internal
600 
601 
602  /*----------------------.
603  | Static manipulators. |
604  `----------------------*/
605 
606  template <unsigned D>
607  inline
608  unsigned
609  complex<D>::nfaces() const
610  {
611  return fold_left_(internal::add_size(), 0);
612  }
613 
614  template <unsigned D>
615  template <unsigned N>
616  inline
617  unsigned
618  complex<D>::nfaces_of_static_dim() const
619  {
620  // Upcast `data_' to get access to the field `faces_' of its
621  // base class `internal::faces_set_mixin<N, D>'.
622  const std::vector< face_data<N, D> >& faces_n =
623  static_cast< const internal::faces_set_mixin<N, D>& >(*data_).faces_;
624  return faces_n.size();
625  }
626 
627 
628  /*-----------------------.
629  | Dynamic manipulators. |
630  `-----------------------*/
631 
632  template <unsigned D>
633  inline
634  unsigned
635  complex<D>::nfaces_of_dim(unsigned n) const
636  {
637  // Ensure N is compatible with D.
638  mln_precondition(n <= D);
639  return apply_if_dim_matches_(n, internal::get_size());
640  }
641 
642 
643  /*-------------------.
644  | Internal methods. |
645  `-------------------*/
646 
647  template <unsigned D>
648  template <unsigned N>
649  inline
651  complex<D>::face_data_(unsigned face_id)
652  {
653  // Upcast `data_' to get access to the field `faces_' of its
654  // base class `internal::faces_set_mixin<N, D>'.
655  std::vector< face_data<N, D> >& faces_n =
656  static_cast< internal::faces_set_mixin<N, D>& >(*data_).faces_;
657  return faces_n[face_id];
658  }
659 
660  template <unsigned D>
661  template <unsigned N>
662  inline
663  const face_data<N, D>&
664  complex<D>::face_data_(unsigned face_id) const
665  {
666  // Upcast `data_' to get access to the field `faces_' of its
667  // base class `internal::faces_set_mixin<N, D>'.
668  const std::vector< face_data<N, D> >& faces_n =
669  static_cast< const internal::faces_set_mixin<N, D>& >(*data_).faces_;
670  return faces_n[face_id];
671  }
672 
673  template <unsigned D>
674  template <unsigned N>
675  inline
676  void
677  complex<D>::connect_(const algebraic_n_face<N, D>& f1,
678  const n_face<N + 1, D>& f2)
679  {
680  // Ensure N is compatible with D.
681  metal::bool_< N <= D >::check();
682 
683  /* Connect
684  - F1, an algebraic n-face,
685  - and AF2, an algebraic (n+1)-face based on F2 and having the
686  sign of F1. */
687  f1.data().connect_higher_dim_face(make_algebraic_n_face(f2, f1.sign()));
688  f2.data().connect_lower_dim_face(f1);
689  }
690 
691 
692  /*-------------.
693  | Comparison. |
694  `-------------*/
695 
696  template <unsigned D>
697  inline
698  bool
699  operator==(const complex<D>& lhs, const complex<D>& rhs)
700  {
701  return lhs.data_.ptr_ == rhs.data_.ptr_;
702  }
703 
704 
705  /*------------------.
706  | Pretty-printing. |
707  `------------------*/
708 
709  template <unsigned D>
710  inline
711  std::ostream&
712  operator<<(std::ostream& ostr, const complex<D>& c)
713  {
714  c.print(ostr);
715  return ostr;
716  }
717 
718  template <unsigned D>
719  inline
720  void
721  complex<D>::print(std::ostream& ostr) const
722  {
723  // Upcast `data_' to get access to the method `print_rec_asc' of
724  // its base class `internal::faces_set_mixin<D, D>'.
725  static_cast< const internal::faces_set_mixin<D, D>& >(*data_).print_rec_asc(ostr);
726  }
727 
728  template <unsigned D>
729  template <unsigned N>
730  inline
731  void
732  complex<D>::print_faces(std::ostream& ostr) const
733  {
734  // Ensure N is compatible with D.
735  metal::bool_< N <= D >::check();
736 
737  // Upcast `data_' to get access to the method `print' of its
738  // base class `internal::faces_set_mixin<N, D>'.
739  static_cast< const internal::faces_set_mixin<N, D>& >(*data_).print(ostr);
740  }
741 
742  template <unsigned D>
743  inline
744  const void*
745  complex<D>::addr() const
746  {
747  return data_.ptr_;
748  }
749 
750 
751  namespace internal
752  {
753 
754  template <unsigned N, unsigned D>
755  inline
756  void
757  faces_set_mixin<N, D>::print_rec_asc(std::ostream& ostr) const
758  {
759  faces_set_mixin<N - 1, D>::print_rec_asc(ostr);
760  print(ostr);
761  }
762 
763  template <unsigned D>
764  inline
765  void
766  faces_set_mixin<0, D>::print_rec_asc(std::ostream& ostr) const
767  {
768  print(ostr);
769  }
770 
771  template <unsigned D>
772  inline
773  void
774  faces_set_mixin<D, D>::print_rec_asc(std::ostream& ostr) const
775  {
777  print(ostr);
778  }
779 
780  inline
781  void
782  faces_set_mixin<0, 0>::print_rec_asc(std::ostream& ostr) const
783  {
784  print(ostr);
785  }
786 
787 
788  template <unsigned N, unsigned D>
789  inline
790  void
791  faces_set_mixin<N, D>::print(std::ostream& ostr) const
792  {
793  ostr << "Faces of dimension " << N
794  << " and their ajacent faces of dimension "
795  << N - 1 << " and "
796  << N + 1 << std::endl;
797  for (unsigned f = 0; f < faces_.size(); ++f)
798  {
799  ostr << " " << f << ": dim " << N - 1 << ": { ";
800  lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
801  ostr << "}, dim " << N + 1 << ": { ";
802  higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
803  ostr << "}" << std::endl;
804  }
805  }
806 
807  template <unsigned D>
808  inline
809  void
810  faces_set_mixin<0, D>::print(std::ostream& ostr) const
811  {
812  const unsigned N = 0;
813  ostr << "Faces of dimension " << N
814  << " and their ajacent faces of dimension "
815  << N + 1 << std::endl;
816  for (unsigned f = 0; f < faces_.size(); ++f)
817  {
818  ostr << " " << f << ": dim " << N + 1 << ": { ";
819  higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
820  ostr << "}" << std::endl;
821  }
822  }
823 
824  template <unsigned D>
825  inline
826  void
827  faces_set_mixin<D, D>::print(std::ostream& ostr) const
828  {
829  const unsigned N = D;
830  ostr << "Faces of dimension " << N
831  << " and their ajacent faces of dimension "
832  << N - 1 << std::endl;
833  for (unsigned f = 0; f < faces_.size(); ++f)
834  {
835  ostr << " " << f << ": dim " << N - 1 << ": { ";
836  lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]);
837  ostr << "}" << std::endl;
838  }
839  }
840 
841  inline
842  void
843  faces_set_mixin<0, 0>::print(std::ostream& ostr) const
844  {
845  const unsigned N = 0;
846  ostr << "Faces of dimension " << N << std::endl;
847  for (unsigned f = 0; f < faces_.size(); ++f)
848  ostr << " " << f << std::endl;
849  }
850 
851 
852  template <unsigned N, unsigned D>
853  inline
854  void
855  lower_dim_faces_set_mixin<N, D>::print(std::ostream& ostr,
856  const face_data<N, D>& f) const
857  {
858  for (typename std::vector< algebraic_n_face<N - 1, D> >::const_iterator l =
859  f.lower_dim_faces_.begin(); l != f.lower_dim_faces_.end(); ++l)
860  ostr << l->face_id() << " ";
861  }
862 
863  template <unsigned N, unsigned D>
864  inline
865  void
866  higher_dim_faces_set_mixin<N, D>::print(std::ostream& ostr,
867  const face_data<N, D>& f) const
868  {
869  for (typename std::vector< algebraic_n_face<N + 1, D> >::const_iterator h =
870  f.higher_dim_faces_.begin(); h != f.higher_dim_faces_.end(); ++h)
871  ostr << h->face_id() << " ";
872  }
873 
874  } // end of namespace mln::topo::internal
875 
876 
877  /*-------------------------------.
878  | Functional meta-manipulators. |
879  `-------------------------------*/
880 
881  /* ------------------------------- */
882  /* ``Static Fold Left'' Operator. */
883  /* ------------------------------- */
884 
885  template <unsigned D>
886  template <typename BinaryFunction, typename T>
887  inline
888  T
889  complex<D>::fold_left_(const BinaryFunction& f, const T& accu) const
890  {
891  // Upcast `data_' to get access to the method `fold_left_' of
892  // its base class `internal::faces_set_mixin<D, D>'.
893  return static_cast< const internal::faces_set_mixin<D, D>& >(*data_).fold_left_(f, accu);
894  }
895 
896  namespace internal
897  {
898 
899  // FIXME: Try to factor.
900 
901  template <unsigned D>
902  template <typename BinaryFunction, typename T>
903  inline
904  T
905  faces_set_mixin<D, D>::fold_left_(const BinaryFunction& f,
906  const T& accu) const
907  {
908  // Upcast `data_' to get access to the method `fold_left_' of
909  // its base class `internal::faces_set_mixin<D - 1, D>'.
910  return static_cast< const faces_set_mixin<D - 1, D>& >(*this).fold_left_(f, f(accu, faces_));
911  }
912 
913  template <unsigned N, unsigned D>
914  template <typename BinaryFunction, typename T>
915  inline
916  T
917  faces_set_mixin<N, D>::fold_left_(const BinaryFunction& f,
918  const T& accu) const
919  {
920  // Upcast `data_' to get access to the method `fold_left_' of
921  // its base class `internal::faces_set_mixin<N - 1, D>'.
922  return static_cast< const faces_set_mixin<N - 1, D>& >(*this).fold_left_(f, f(accu, faces_));
923  }
924 
925  template <unsigned D>
926  template <typename BinaryFunction, typename T>
927  inline
928  T
929  faces_set_mixin<0, D>::fold_left_(const BinaryFunction& f,
930  const T& accu) const
931  {
932  return f(accu, faces_);
933  }
934 
935  template <typename BinaryFunction, typename T>
936  inline
937  T
938  faces_set_mixin<0, 0>::fold_left_(const BinaryFunction& f,
939  const T& accu) const
940  {
941  return f(accu, faces_);
942  }
943 
944  } // end of namespace mln::topo::internal
945 
946 
947  /* ------------------------------------------------ */
948  /* ``Static Apply-If-Dimension-Matches'' Operator. */
949  /* ------------------------------------------------ */
950 
951  template <unsigned D>
952  template <typename UnaryFunction>
953  inline
954  typename UnaryFunction::result_type
955  complex<D>::apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const
956  {
957  // Ensure N is compatible with D.
958  mln_precondition(n <= D);
959  // Upcast `data_' to get access to the method `apply_if_dim_matches_' of
960  // its base class `internal::faces_set_mixin<D, D>'.
961  return static_cast< const internal::faces_set_mixin<D, D>& >(*data_).apply_if_dim_matches_(n, f);
962  }
963 
964  namespace internal
965  {
966 
967  // FIXME: Try to factor.
968 
969  template <unsigned D>
970  template <typename UnaryFunction>
971  inline
972  typename UnaryFunction::result_type
974  const UnaryFunction& f) const
975  {
976  // Ensure N and D are compatible.
977  mln_precondition(n <= D);
978  return n == D ?
979  f(faces_) :
980  faces_set_mixin<D - 1, D>::apply_if_dim_matches_(n, f);
981  }
982 
983  template <unsigned N, unsigned D>
984  template <typename UnaryFunction>
985  inline
986  typename UnaryFunction::result_type
987  faces_set_mixin<N, D>::apply_if_dim_matches_(unsigned n,
988  const UnaryFunction& f) const
989  {
990  // Ensure N and D are compatible.
991  mln_precondition(n <= D);
992  return n == N ?
993  f(faces_) :
994  faces_set_mixin<N - 1, D>::apply_if_dim_matches_(n, f);
995  }
996 
997  template <unsigned D>
998  template <typename UnaryFunction>
999  inline
1000  typename UnaryFunction::result_type
1002  const UnaryFunction& f) const
1003  {
1004  // If we reached this method, then N should be 0.
1005  mln_precondition(n == 0);
1006  // Prevent ``unused variable'' warnings when NDEBUG is defined.
1007  (void) n;
1008  return f(faces_);
1009  }
1010 
1011  template <typename UnaryFunction>
1012  inline
1013  typename UnaryFunction::result_type
1015  const UnaryFunction& f) const
1016  {
1017  // If we reached this method, then N should be 0.
1018  mln_precondition(n == 0);
1019  // Prevent ``unused variable'' warnings when NDEBUG is defined.
1020  (void) n;
1021  return f(faces_);
1022  }
1023 
1024  } // end of namespace mln::topo::internal
1025 
1026 # endif // ! MLN_INCLUDE_ONLY
1027 
1028  } // end of namespace mln::topo
1029 
1030 } // end of namespace mln
1031 
1032 #endif // ! MLN_TOPO_COMPLEX_HH