[PATCH 08/22] Work around std::vector<bool> specialization in mln::complex_image.

* mln/core/image/complex_image.hh (mln::internal::bool_proxy): New class. (mln::internal::unbool<V>:): New trait class. (mlc_unbool): New (local) shortcut macro. (mln::internal::data< complex_image<D, G, V> >::values_): Change type from metal::vec< D + 1, std::vector<V> > to metal::vec< D + 1, std::vector< mlc_unbool(V) > >. (mln::complex_image<D, G, V>::lvalue) (mln::complex_image<D, G, V>::rvalue): Adjust typedefs. (mln::complex_image<D, G, V>::values() const): Adjust method. (data< complex_image<D, G, V> >::data): Adjust ctor. Simplify precondition. (complex_image<D, G, V>::complex_image(const p_complex<D, G>&)): Simplify. (init_(image_t, complex_image<D,G,V>&, const complex_image<D,G,W>&)): Depend on model's domain instead of its values to compute the number of n-faces. --- milena/ChangeLog | 25 +++++++++++ milena/mln/core/image/complex_image.hh | 73 +++++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 15 deletions(-) diff --git a/milena/ChangeLog b/milena/ChangeLog index 43d281c..4215c0c 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,28 @@ +2009-09-29 Roland Levillain <roland@lrde.epita.fr> + + Work around std::vector<bool> specialization in mln::complex_image. + + * mln/core/image/complex_image.hh + (mln::internal::bool_proxy): New class. + (mln::internal::unbool<V>:): New trait class. + (mlc_unbool): New (local) shortcut macro. + (mln::internal::data< complex_image<D, G, V> >::values_): + Change type from metal::vec< D + 1, std::vector<V> > + to metal::vec< D + 1, std::vector< mlc_unbool(V) > >. + (mln::complex_image<D, G, V>::lvalue) + (mln::complex_image<D, G, V>::rvalue): + Adjust typedefs. + (mln::complex_image<D, G, V>::values() const): + Adjust method. + (data< complex_image<D, G, V> >::data): + Adjust ctor. + Simplify precondition. + (complex_image<D, G, V>::complex_image(const p_complex<D, G>&)): + Simplify. + (init_(image_t, complex_image<D,G,V>&, const complex_image<D,G,W>&)): + Depend on model's domain instead of its values to compute the + number of n-faces. + 2009-09-28 Roland Levillain <roland@lrde.epita.fr> Miscellaneous corrections to complex_window_base. diff --git a/milena/mln/core/image/complex_image.hh b/milena/mln/core/image/complex_image.hh index 9f273a5..07c6e91 100644 --- a/milena/mln/core/image/complex_image.hh +++ b/milena/mln/core/image/complex_image.hh @@ -40,6 +40,45 @@ # include <mln/core/site_set/complex_psite.hh> # include <mln/value/set.hh> +// FIXME: Move this elsewhere. +// Working around std::vector<bool>'s (forced) specialization. + +# define mlc_unbool(V) \ + typename mln::internal::unbool<V>::ret + +namespace mln +{ + + namespace internal + { + + /// A boolean proxy, used to fool std::vector. + struct bool_proxy + { + public: + bool_proxy() {} + bool_proxy(bool b) : b_(b) {} + bool& operator=(bool b) { b_ = b; return *this; } + + operator bool&() { return b_; } + operator const bool&() const { return b_; } + + bool operator==(const bool_proxy& rhs) { return b_ == rhs.b_; } + bool operator< (const bool_proxy& rhs) { return b_ < rhs.b_; } + + private: + /// The value. + bool b_; + }; + + template <typename V> struct unbool { typedef V ret; }; + template <> struct unbool<bool> { typedef bool_proxy ret; }; + + } // end of namespace mln::internal + +} + + /* FIXME: In the current implementation, the type of values on faces of different dimensions is necessarily the same (V). We should @@ -62,7 +101,7 @@ namespace mln data(const p_complex<D, G>& pc, const metal::vec< D + 1, std::vector<V> >& values); - metal::vec< D + 1, std::vector<V> > values_; + metal::vec< D + 1, std::vector< mlc_unbool(V) > > values_; const p_complex<D, G> pc_; }; @@ -135,15 +174,10 @@ namespace mln typedef V value; /// Return type of read-write access. - /// - /// We use the associated type \c reference instead of a plain - /// reference on the value type (\p V), because it's the only way - /// to safely form a reference on the element in the case of a - /// std::vector<bool>. - typedef typename std::vector<V>::reference lvalue; + typedef V& lvalue; /// Return type of read-only access. - typedef typename std::vector<V>::const_reference rvalue; + typedef const V& rvalue; /// Skeleton. typedef complex_image< D, tag::psite_<G>, tag::value_<V> > skeleton; @@ -172,7 +206,7 @@ namespace mln const p_complex<D, G>& domain() const; /// Return the array of values associated to the faces. - const metal::vec<D + 1, std::vector<V> >& values() const; + const metal::vec<D + 1, std::vector< mlc_unbool(V) > >& values() const; /// \} }; @@ -197,7 +231,7 @@ namespace mln { metal::vec<D + 1, std::vector<V> > values; for (unsigned i = 0; i <= D; ++i) - values[i].resize(model.values()[i].size()); + values[i].resize(model.domain().nfaces_of_dim(i)); target.init_(model.domain(), values); } @@ -211,15 +245,23 @@ namespace mln inline data< complex_image<D, G, V> >::data(const p_complex<D, G>& pc, const metal::vec< D + 1, std::vector<V> >& values) - : values_(values), - pc_(pc) + : pc_(pc) { + // We cannot use the initialization list for values_ (it + // would not work when V = bool). + for (unsigned i = 0; i <= D; ++i) + { + values_[i].reserve(values[i].size()); + values_[i].insert(values_[i].begin(), + values[i].begin(), values[i].end()); + } + // Ensure the complex is consistent with the values. /* FIXME: We need additional macros in mln/core/contract.hh for big blocks of preconditions like this one. */ # ifndef NDEBUG for (unsigned i = 0; i < D; ++i) - mln_precondition(pc.cplx().nfaces_of_dim(i) == values[i].size()); + mln_precondition(pc.nfaces_of_dim(i) == values[i].size()); # endif // !NDEBUG } @@ -241,7 +283,7 @@ namespace mln { metal::vec<D + 1, std::vector<V> > values; for (unsigned i = 0; i <= D; ++i) - values[i].resize(pc.cplx().nfaces_of_dim(i)); + values[i].resize(pc.nfaces_of_dim(i)); init_(pc, values); } @@ -289,7 +331,7 @@ namespace mln template <unsigned D, typename G, typename V> inline - const metal::vec< D + 1, std::vector<V> >& + const metal::vec< D + 1, std::vector< mlc_unbool(V) > >& complex_image<D, G, V>::values() const { return this->data_->values_; @@ -308,5 +350,6 @@ namespace mln } // end of namespace mln +# undef mlc_unbool #endif // ! MLN_CORE_IMAGE_COMPLEX_IMAGE_HH -- 1.6.3.1
participants (1)
-
Roland Levillain