Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2008, 2009, 2010 EPITA Research and Development 00002 // Laboratory (LRDE) 00003 // 00004 // This file is part of Olena. 00005 // 00006 // Olena is free software: you can redistribute it and/or modify it under 00007 // the terms of the GNU General Public License as published by the Free 00008 // Software Foundation, version 2 of the License. 00009 // 00010 // Olena is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 // As a special exception, you may use this file as part of a free 00019 // software project without restriction. Specifically, if other files 00020 // instantiate templates or use macros or inline functions from this 00021 // file, or you compile this file and link it with other files to produce 00022 // an executable, this file does not by itself cause the resulting 00023 // executable to be covered by the GNU General Public License. This 00024 // exception does not however invalidate any other reasons why the 00025 // executable file might be covered by the GNU General Public License. 00026 00027 #ifndef MLN_TOPO_COMPLEX_HH 00028 # define MLN_TOPO_COMPLEX_HH 00029 00036 00037 # include <cstddef> 00038 00039 # include <iosfwd> 00040 00041 # include <mln/metal/bool.hh> 00042 00043 # include <mln/util/tracked_ptr.hh> 00044 00045 # include <mln/topo/face_data.hh> 00046 # include <mln/topo/algebraic_face.hh> 00047 # include <mln/topo/algebraic_n_face.hh> 00048 # include <mln/topo/n_faces_set.hh> 00049 00050 # include <mln/topo/complex_iterators.hh> 00051 00052 00053 namespace mln 00054 { 00055 00056 namespace topo 00057 { 00058 00059 // Forward declarations (external). 00060 template <unsigned N, unsigned D> class n_faces_set; 00061 template <unsigned D> class face_fwd_iter; 00062 template <unsigned D> class face_bkd_iter; 00063 // FIXME: Disabled (moved to the attic). 00064 # if 0 00065 template <unsigned N, unsigned D> class faces_fwd_iter_; 00066 template <unsigned N, unsigned D> class faces_bkd_iter_; 00067 #endif 00068 00069 // Forward declarations (internal). 00070 namespace internal 00071 { 00072 template <unsigned D> 00073 struct complex_data; 00074 00075 template <unsigned N, unsigned D> 00076 struct faces_set_mixin; 00077 } 00078 00079 00080 /*----------. 00081 | Complex. | 00082 `----------*/ 00083 00085 // 00086 template <unsigned D> 00087 class complex 00088 { 00089 public: 00091 typedef face_fwd_iter<D> fwd_citer; 00093 typedef face_bkd_iter<D> bkd_citer; 00094 00095 // FIXME: Disabled (moved to the attic). 00096 # if 0 00097 00098 template <unsigned N> 00099 struct fwd_fiter { typedef faces_fwd_iter_<N, D> ret; }; 00101 template <unsigned N> 00102 struct bkd_fiter { typedef faces_bkd_iter_<N, D> ret; }; 00103 #endif 00104 00108 complex(); 00109 00111 n_face<0u, D> add_face(); 00112 00117 template <unsigned N> 00118 n_face<N + 1, D> add_face(const n_faces_set<N, D>& adjacent_faces); 00120 00127 unsigned nfaces() const; 00128 00130 template <unsigned N> 00131 unsigned nfaces_of_static_dim() const; 00133 00144 unsigned nfaces_of_dim(unsigned n) const; 00146 00150 void print(std::ostream& ostr) const; 00152 template <unsigned N> 00153 void print_faces(std::ostream& ostr) const; 00155 00160 const void* addr() const; 00161 00162 private: 00164 util::tracked_ptr< internal::complex_data<D> > data_; 00165 00166 template <unsigned D_> 00167 friend bool operator==(const complex<D_>& lhs, const complex<D_>& rhs); 00168 00171 template <unsigned N, unsigned D_> friend class n_face; 00172 template <unsigned D_> friend class face; 00173 00174 template <unsigned N> 00175 face_data<N, D>& face_data_(unsigned face_id); 00176 00177 template <unsigned N> 00178 const face_data<N, D>& face_data_(unsigned face_id) const; 00180 00183 /* FIXME: Use something more constraining than the STL's 00184 UnaryFunction/BinaryFunction. Use Function or Function_v2v? 00185 Or a new subclass of Function? */ 00186 00187 /* FIXME: Replace F and ACCU by a Milena accumulator? */ 00188 00198 template <typename BinaryFunction, typename T> 00199 T fold_left_(const BinaryFunction& f, const T& accu) const; 00200 00202 template <typename UnaryFunction> 00203 typename UnaryFunction::result_type 00204 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; 00206 00213 template <unsigned N> 00214 void connect_(const algebraic_n_face<N, D>& f1, 00215 const n_face<N + 1, D>& f2); 00216 }; 00217 00218 00220 template <unsigned D> 00221 bool 00222 operator==(const complex<D>& lhs, const complex<D>& rhs); 00223 00224 00226 template <unsigned D> 00227 std::ostream& 00228 operator<<(std::ostream& ostr, const complex<D>& c); 00229 00230 00231 /*---------------. 00232 | Complex data. | 00233 `---------------*/ 00234 00289 /*---------------------. 00290 | Faces of a complex. | 00291 `---------------------*/ 00292 00295 namespace internal 00296 { 00297 00298 // Forward declarations. 00299 template <unsigned N, unsigned D> struct lower_dim_faces_set_mixin; 00300 template <unsigned N, unsigned D> struct higher_dim_faces_set_mixin; 00301 00302 // -------------------------------------- // 00303 // mln::topo::internal::faces_set_mixin. // 00304 // -------------------------------------- // 00305 00308 00309 template <unsigned N, unsigned D> struct faces_set_mixin; 00310 00311 00313 template <unsigned N, unsigned D> 00314 struct faces_set_mixin : public faces_set_mixin<N - 1, D>, 00315 public lower_dim_faces_set_mixin<N, D>, 00316 public higher_dim_faces_set_mixin<N, D> 00317 { 00318 std::vector< face_data<N, D> > faces_; 00319 00323 void print(std::ostream& ostr) const; 00326 void print_rec_asc(std::ostream& ostr) const; 00328 00333 template <typename BinaryFunction, typename T> 00334 T fold_left_(const BinaryFunction& f, const T& accu) const; 00337 template <typename UnaryFunction> 00338 typename UnaryFunction::result_type 00339 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; 00341 }; 00342 00344 template <unsigned D> 00345 struct faces_set_mixin<D, D> : public faces_set_mixin<D - 1, D>, 00346 public lower_dim_faces_set_mixin<D, D> 00347 { 00348 std::vector< face_data<D, D> > faces_; 00349 00353 void print(std::ostream& ostr) const; 00354 void print_rec_asc(std::ostream& ostr) const; 00356 00361 template <typename BinaryFunction, typename T> 00362 T fold_left_(const BinaryFunction& f, const T& accu) const; 00365 template <typename UnaryFunction> 00366 typename UnaryFunction::result_type 00367 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; 00369 }; 00370 00372 template <unsigned D> 00373 struct faces_set_mixin<0u, D> : public higher_dim_faces_set_mixin<0u, D> 00374 { 00375 std::vector< face_data<0u, D> > faces_; 00376 00380 void print(std::ostream& ostr) const; 00381 void print_rec_asc(std::ostream& ostr) const; 00383 00388 template <typename BinaryFunction, typename T> 00389 T fold_left_(const BinaryFunction& f, const T& accu) const; 00392 template <typename UnaryFunction> 00393 typename UnaryFunction::result_type 00394 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; 00396 }; 00397 00399 template <> 00400 struct faces_set_mixin<0u, 0u> 00401 { 00402 std::vector< face_data<0u, 0u> > faces_; 00403 00407 void print(std::ostream& ostr) const; 00408 void print_rec_asc(std::ostream& ostr) const; 00410 00415 template <typename BinaryFunction, typename T> 00416 T fold_left_(const BinaryFunction& f, const T& accu) const; 00419 template <typename UnaryFunction> 00420 typename UnaryFunction::result_type 00421 apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; 00423 }; 00425 00426 00427 // Tech note: g++-2.95 highly prefers to have the complex_data 00428 // class to be defined after the specializations of 00429 // 'faces_set_mixin'. 00430 00432 template <unsigned D> 00433 struct complex_data : public faces_set_mixin<D, D> 00434 { 00435 // Data is contained in super classes. 00436 }; 00437 00438 00439 // ------------------------------------------------- // 00440 // mln::topo::internal::lower_dim_faces_set_mixin. // 00441 // mln::topo::internal::higher_dim_faces_set_mixin. // 00442 // ------------------------------------------------- // 00443 00446 template <unsigned N, unsigned D> 00447 struct lower_dim_faces_set_mixin 00448 { 00449 void print(std::ostream& ostr, const face_data<N, D>& f) const; 00450 }; 00451 00452 template <unsigned N, unsigned D> 00453 struct higher_dim_faces_set_mixin 00454 { 00455 void print(std::ostream& ostr, const face_data<N, D>& f) const; 00456 }; 00458 00459 } // end of namespace mln::topo::internal 00460 00461 00462 00463 # ifndef MLN_INCLUDE_ONLY 00464 00465 /*-----------------------. 00466 | Complex construction. | 00467 `-----------------------*/ 00468 00469 template <unsigned D> 00470 inline 00471 complex<D>::complex() 00472 // Allocate data for this complex. 00473 : data_(new internal::complex_data<D>()) 00474 { 00475 } 00476 00477 template <unsigned D> 00478 inline 00479 n_face<0u, D> 00480 complex<D>::add_face() 00481 { 00482 /* FIXME: This is not thread-proof (these two lines should 00483 form an atomic section). */ 00484 data_->internal::faces_set_mixin<0u, D>::faces_.push_back(face_data<0u, D>()); 00485 unsigned id = nfaces_of_static_dim<0u>() - 1; 00486 return n_face<0u, D>(*this, id); 00487 } 00488 00489 template <unsigned D> 00490 template <unsigned N> 00491 inline 00492 n_face<N + 1, D> 00493 complex<D>::add_face(const n_faces_set<N, D>& adjacent_faces) 00494 { 00495 typedef typename std::vector< algebraic_n_face<N, D> >::const_iterator 00496 iter_t; 00497 00498 // Ensure ADJACENT_FACES are already part of the complex. 00499 if (!HAS_NDEBUG) 00500 for (iter_t a = adjacent_faces.faces().begin(); 00501 a != adjacent_faces.faces().end(); ++a) 00502 { 00503 mln_precondition(a->cplx() == *this); 00504 mln_precondition(a->is_valid()); 00505 } 00506 00507 face_data<N + 1, D> f; 00508 /* FIXME: This is not thread-proof (these two lines should 00509 form an atomic section). */ 00510 data_->internal::faces_set_mixin<N + 1, D>::faces_.push_back(f); 00511 unsigned id = nfaces_of_static_dim<N + 1>() - 1; 00512 00513 n_face<N + 1, D> fh(*this, id); 00514 // Connect F and its ADJACENT_FACES. 00515 for (iter_t a = adjacent_faces.faces().begin(); 00516 a != adjacent_faces.faces().end(); ++a) 00517 /* Connect 00518 - algebraic n-face *A, 00519 - and an (n+1)-algebraic face based on FH and having the 00520 sign of *A. */ 00521 connect_(*a, fh); 00522 return fh; 00523 } 00524 00525 00526 /*-------. 00527 | Misc. | 00528 `-------*/ 00529 00530 namespace internal 00531 { 00532 00541 struct add_size 00542 { 00543 template <typename T, typename Container> 00544 T operator()(const T& x, const Container& c) const 00545 { 00546 return x + c.size(); 00547 } 00548 }; 00549 00558 struct get_size 00559 { 00560 typedef std::size_t result_type; 00561 00562 template <typename Container> 00563 typename Container::size_type operator()(const Container& c) const 00564 { 00565 return c.size(); 00566 } 00567 }; 00568 00569 } // end of namespace mln::topo::internal 00570 00571 00572 /*----------------------. 00573 | Static manipulators. | 00574 `----------------------*/ 00575 00576 template <unsigned D> 00577 inline 00578 unsigned 00579 complex<D>::nfaces() const 00580 { 00581 return fold_left_(internal::add_size(), 0); 00582 } 00583 00584 template <unsigned D> 00585 template <unsigned N> 00586 inline 00587 unsigned 00588 complex<D>::nfaces_of_static_dim() const 00589 { 00590 return data_->internal::faces_set_mixin<N, D>::faces_.size(); 00591 } 00592 00593 00594 /*-----------------------. 00595 | Dynamic manipulators. | 00596 `-----------------------*/ 00597 00598 template <unsigned D> 00599 inline 00600 unsigned 00601 complex<D>::nfaces_of_dim(unsigned n) const 00602 { 00603 // Ensure N is compatible with D. 00604 mln_precondition(n <= D); 00605 return apply_if_dim_matches_(n, internal::get_size()); 00606 } 00607 00608 00609 /*-------------------. 00610 | Internal methods. | 00611 `-------------------*/ 00612 00613 template <unsigned D> 00614 template <unsigned N> 00615 inline 00616 face_data<N, D>& 00617 complex<D>::face_data_(unsigned face_id) 00618 { 00619 return data_->internal::faces_set_mixin<N, D>::faces_[face_id]; 00620 } 00621 00622 template <unsigned D> 00623 template <unsigned N> 00624 inline 00625 const face_data<N, D>& 00626 complex<D>::face_data_(unsigned face_id) const 00627 { 00628 return data_->internal::faces_set_mixin<N, D>::faces_[face_id]; 00629 } 00630 00631 template <unsigned D> 00632 template <unsigned N> 00633 inline 00634 void 00635 complex<D>::connect_(const algebraic_n_face<N, D>& f1, 00636 const n_face<N + 1, D>& f2) 00637 { 00638 // Ensure N is compatible with D. 00639 metal::bool_< N <= D >::check(); 00640 00641 /* Connect 00642 - F1, an algebraic n-face, 00643 - and AF2, an algebraic (n+1)-face based on F2 and having the 00644 sign of F1. */ 00645 f1.data().connect_higher_dim_face(make_algebraic_n_face(f2, f1.sign())); 00646 f2.data().connect_lower_dim_face(f1); 00647 } 00648 00649 00650 /*-------------. 00651 | Comparison. | 00652 `-------------*/ 00653 00654 template <unsigned D> 00655 inline 00656 bool 00657 operator==(const complex<D>& lhs, const complex<D>& rhs) 00658 { 00659 return lhs.data_.ptr_ == rhs.data_.ptr_; 00660 } 00661 00662 00663 /*------------------. 00664 | Pretty-printing. | 00665 `------------------*/ 00666 00667 template <unsigned D> 00668 inline 00669 std::ostream& 00670 operator<<(std::ostream& ostr, const complex<D>& c) 00671 { 00672 c.print(ostr); 00673 return ostr; 00674 } 00675 00676 template <unsigned D> 00677 inline 00678 void 00679 complex<D>::print(std::ostream& ostr) const 00680 { 00681 data_->internal::faces_set_mixin<D, D>::print_rec_asc(ostr); 00682 } 00683 00684 template <unsigned D> 00685 template <unsigned N> 00686 inline 00687 void 00688 complex<D>::print_faces(std::ostream& ostr) const 00689 { 00690 // Ensure N is compatible with D. 00691 metal::bool_< N <= D >::check(); 00692 00693 data_->internal::faces_set_mixin<N, D>::print(ostr); 00694 } 00695 00696 template <unsigned D> 00697 inline 00698 const void* 00699 complex<D>::addr() const 00700 { 00701 return data_.ptr_; 00702 } 00703 00704 00705 namespace internal 00706 { 00707 00708 template <unsigned N, unsigned D> 00709 inline 00710 void 00711 faces_set_mixin<N, D>::print_rec_asc(std::ostream& ostr) const 00712 { 00713 faces_set_mixin<N - 1, D>::print_rec_asc(ostr); 00714 print(ostr); 00715 } 00716 00717 template <unsigned D> 00718 inline 00719 void 00720 faces_set_mixin<0u, D>::print_rec_asc(std::ostream& ostr) const 00721 { 00722 print(ostr); 00723 } 00724 00725 template <unsigned D> 00726 inline 00727 void 00728 faces_set_mixin<D, D>::print_rec_asc(std::ostream& ostr) const 00729 { 00730 faces_set_mixin<D - 1, D>::print_rec_asc(ostr); 00731 print(ostr); 00732 } 00733 00734 inline 00735 void 00736 faces_set_mixin<0u, 0u>::print_rec_asc(std::ostream& ostr) const 00737 { 00738 print(ostr); 00739 } 00740 00741 00742 template <unsigned N, unsigned D> 00743 inline 00744 void 00745 faces_set_mixin<N, D>::print(std::ostream& ostr) const 00746 { 00747 ostr << "Faces of dimension " << N 00748 << " and their ajacent faces of dimension " 00749 << N - 1 << " and " 00750 << N + 1 << std::endl; 00751 for (unsigned f = 0; f < faces_.size(); ++f) 00752 { 00753 ostr << " " << f << ": dim " << N - 1 << ": { "; 00754 lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); 00755 ostr << "}, dim " << N + 1 << ": { "; 00756 higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); 00757 ostr << "}" << std::endl; 00758 } 00759 } 00760 00761 template <unsigned D> 00762 inline 00763 void 00764 faces_set_mixin<0u, D>::print(std::ostream& ostr) const 00765 { 00766 const unsigned N = 0u; 00767 ostr << "Faces of dimension " << N 00768 << " and their ajacent faces of dimension " 00769 << N + 1 << std::endl; 00770 for (unsigned f = 0; f < faces_.size(); ++f) 00771 { 00772 ostr << " " << f << ": dim " << N + 1 << ": { "; 00773 higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); 00774 ostr << "}" << std::endl; 00775 } 00776 } 00777 00778 template <unsigned D> 00779 inline 00780 void 00781 faces_set_mixin<D, D>::print(std::ostream& ostr) const 00782 { 00783 const unsigned N = D; 00784 ostr << "Faces of dimension " << N 00785 << " and their ajacent faces of dimension " 00786 << N - 1 << std::endl; 00787 for (unsigned f = 0; f < faces_.size(); ++f) 00788 { 00789 ostr << " " << f << ": dim " << N - 1 << ": { "; 00790 lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); 00791 ostr << "}" << std::endl; 00792 } 00793 } 00794 00795 inline 00796 void 00797 faces_set_mixin<0u, 0u>::print(std::ostream& ostr) const 00798 { 00799 const unsigned N = 0u; 00800 ostr << "Faces of dimension " << N << std::endl; 00801 for (unsigned f = 0; f < faces_.size(); ++f) 00802 ostr << " " << f << std::endl; 00803 } 00804 00805 00806 template <unsigned N, unsigned D> 00807 inline 00808 void 00809 lower_dim_faces_set_mixin<N, D>::print(std::ostream& ostr, 00810 const face_data<N, D>& f) const 00811 { 00812 for (typename std::vector< algebraic_n_face<N - 1, D> >::const_iterator l = 00813 f.lower_dim_faces_.begin(); l != f.lower_dim_faces_.end(); ++l) 00814 ostr << l->face_id() << " "; 00815 } 00816 00817 template <unsigned N, unsigned D> 00818 inline 00819 void 00820 higher_dim_faces_set_mixin<N, D>::print(std::ostream& ostr, 00821 const face_data<N, D>& f) const 00822 { 00823 for (typename std::vector< algebraic_n_face<N + 1, D> >::const_iterator h = 00824 f.higher_dim_faces_.begin(); h != f.higher_dim_faces_.end(); ++h) 00825 ostr << h->face_id() << " "; 00826 } 00827 00828 } // end of namespace mln::topo::internal 00829 00830 00831 /*-------------------------------. 00832 | Functional meta-manipulators. | 00833 `-------------------------------*/ 00834 00835 /* ------------------------------- */ 00836 /* ``Static Fold Left'' Operator. */ 00837 /* ------------------------------- */ 00838 00839 template <unsigned D> 00840 template <typename BinaryFunction, typename T> 00841 inline 00842 T 00843 complex<D>::fold_left_(const BinaryFunction& f, const T& accu) const 00844 { 00845 return data_->internal::faces_set_mixin<D, D>::fold_left_(f, accu); 00846 } 00847 00848 namespace internal 00849 { 00850 00851 // FIXME: Try to factor. 00852 00853 template <unsigned D> 00854 template <typename BinaryFunction, typename T> 00855 inline 00856 T 00857 faces_set_mixin<D, D>::fold_left_(const BinaryFunction& f, 00858 const T& accu) const 00859 { 00860 return faces_set_mixin<D - 1, D>::fold_left_(f, f(accu, faces_)); 00861 } 00862 00863 template <unsigned N, unsigned D> 00864 template <typename BinaryFunction, typename T> 00865 inline 00866 T 00867 faces_set_mixin<N, D>::fold_left_(const BinaryFunction& f, 00868 const T& accu) const 00869 { 00870 return faces_set_mixin<N - 1, D>::fold_left_(f, f(accu, faces_)); 00871 } 00872 00873 template <unsigned D> 00874 template <typename BinaryFunction, typename T> 00875 inline 00876 T 00877 faces_set_mixin<0u, D>::fold_left_(const BinaryFunction& f, 00878 const T& accu) const 00879 { 00880 return f(accu, faces_); 00881 } 00882 00883 template <typename BinaryFunction, typename T> 00884 inline 00885 T 00886 faces_set_mixin<0u, 0u>::fold_left_(const BinaryFunction& f, 00887 const T& accu) const 00888 { 00889 return f(accu, faces_); 00890 } 00891 00892 } // end of namespace mln::topo::internal 00893 00894 00895 /* ------------------------------------------------ */ 00896 /* ``Static Apply-If-Dimension-Matches'' Operator. */ 00897 /* ------------------------------------------------ */ 00898 00899 template <unsigned D> 00900 template <typename UnaryFunction> 00901 inline 00902 typename UnaryFunction::result_type 00903 complex<D>::apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const 00904 { 00905 // Ensure N is compatible with D. 00906 mln_precondition(n <= D); 00907 return data_->internal::faces_set_mixin<D, D>::apply_if_dim_matches_(n, f); 00908 } 00909 00910 namespace internal 00911 { 00912 00913 // FIXME: Try to factor. 00914 00915 template <unsigned D> 00916 template <typename UnaryFunction> 00917 inline 00918 typename UnaryFunction::result_type 00919 faces_set_mixin<D, D>::apply_if_dim_matches_(unsigned n, 00920 const UnaryFunction& f) const 00921 { 00922 // Ensure N and D are compatible. 00923 mln_precondition(n <= D); 00924 return n == D ? 00925 f(faces_) : 00926 faces_set_mixin<D - 1, D>::apply_if_dim_matches_(n, f); 00927 } 00928 00929 template <unsigned N, unsigned D> 00930 template <typename UnaryFunction> 00931 inline 00932 typename UnaryFunction::result_type 00933 faces_set_mixin<N, D>::apply_if_dim_matches_(unsigned n, 00934 const UnaryFunction& f) const 00935 { 00936 // Ensure N and D are compatible. 00937 mln_precondition(n <= D); 00938 return n == N ? 00939 f(faces_) : 00940 faces_set_mixin<N - 1, D>::apply_if_dim_matches_(n, f); 00941 } 00942 00943 template <unsigned D> 00944 template <typename UnaryFunction> 00945 inline 00946 typename UnaryFunction::result_type 00947 faces_set_mixin<0u, D>::apply_if_dim_matches_(unsigned n, 00948 const UnaryFunction& f) const 00949 { 00950 // If we reached this method, then N should be 0. 00951 mln_precondition(n == 0); 00952 // Prevent ``unused variable'' warnings when NDEBUG is defined. 00953 (void) n; 00954 return f(faces_); 00955 } 00956 00957 template <typename UnaryFunction> 00958 inline 00959 typename UnaryFunction::result_type 00960 faces_set_mixin<0u, 0u>::apply_if_dim_matches_(unsigned n, 00961 const UnaryFunction& f) const 00962 { 00963 // If we reached this method, then N should be 0. 00964 mln_precondition(n == 0); 00965 // Prevent ``unused variable'' warnings when NDEBUG is defined. 00966 (void) n; 00967 return f(faces_); 00968 } 00969 00970 } // end of namespace mln::topo::internal 00971 00972 # endif // ! MLN_INCLUDE_ONLY 00973 00974 } // end of namespace mln::topo 00975 00976 } // end of namespace mln 00977 00978 #endif // ! MLN_TOPO_COMPLEX_HH