3113: Fix data mutability in pw::image.

* mln/core/concept/function.hh: use a mutable_result type instead of using a boolean. It avoids issues with the mutable type which may differ from the result value of the function. Taking a reference on the function result value *must* be different in order to handle the case of a reference on an element in a vector of bool. * mln/fun/i2v/array.hh, * mln/fun/internal/array_base.hh, * mln/fun/l2l/relabel.hh, * mln/pw/image.hh: update in order to use the new mutable_result type. --- milena/ChangeLog | 15 ++++++ milena/mln/core/concept/function.hh | 2 +- milena/mln/fun/i2v/array.hh | 18 +++++--- milena/mln/fun/internal/array_base.hh | 76 ++++++++++++++++++++------------- milena/mln/fun/l2l/relabel.hh | 21 +++++++-- milena/mln/pw/image.hh | 53 +++++++++++++---------- 6 files changed, 120 insertions(+), 65 deletions(-) diff --git a/milena/ChangeLog b/milena/ChangeLog index 57392db..2ea28d6 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,20 @@ 2008-12-30 Guillaume Lazzara <z@lrde.epita.fr> + Fix data mutability in pw::image. + + * mln/core/concept/function.hh: use a mutable_result type + instead of using a boolean. It avoids issues with the mutable type + which may differ from the result value of the function. Taking a + reference on the function result value *must* be different in order to + handle the case of a reference on an element in a vector of bool. + + * mln/fun/i2v/array.hh, + * mln/fun/internal/array_base.hh, + * mln/fun/l2l/relabel.hh, + * mln/pw/image.hh: update in order to use the new mutable_result type. + +2008-12-30 Guillaume Lazzara <z@lrde.epita.fr> + Add a call to center_at_() in site_relative_iterator_base::center_at() (ticket #176). diff --git a/milena/mln/core/concept/function.hh b/milena/mln/core/concept/function.hh index 454a078..8aada68 100644 --- a/milena/mln/core/concept/function.hh +++ b/milena/mln/core/concept/function.hh @@ -100,7 +100,7 @@ namespace mln struct Function_v2v : public Function<E> { typedef Function_v2v<void> category; - typedef metal::false_ is_mutable; // Meaning: no mutable result by default. + typedef void mutable_result; // Meaning: no mutable result by default. protected: Function_v2v(); Function_v2v(const Function_v2v&); diff --git a/milena/mln/fun/i2v/array.hh b/milena/mln/fun/i2v/array.hh index 9bc48ef..f9ce0d1 100644 --- a/milena/mln/fun/i2v/array.hh +++ b/milena/mln/fun/i2v/array.hh @@ -38,7 +38,6 @@ # include <vector> # include <algorithm> # include <mln/fun/internal/array_base.hh> -# include <mln/core/concept/function.hh> # include <mln/util/array.hh> @@ -89,10 +88,9 @@ namespace mln { template <typename T> - class array : public Function_i2v< array<T> >, - public internal::array_base<T> + class array : public internal::array_base< T, array<T> > { - typedef internal::array_base<T> super_base_; + typedef internal::array_base< T, array<T> > super_base_; public: @@ -112,10 +110,8 @@ namespace mln /// Used in from_to(). Constructs that function from an std::vector. /// Always prefer using from_to instead of this constructor. array(const std::vector<T>& from); - /// \} - typedef metal::true_ is_mutable; }; } // end of namespace mln::fun::i2v @@ -126,6 +122,16 @@ namespace mln # ifndef MLN_INCLUDE_ONLY + // Init. + + template <typename T1, typename T2> + void init_(tag::function_t, + fun::i2v::array<T1>& f, + const fun::i2v::array<T2>& model) + { + f.init_(model.size()); + } + // convert::from_to diff --git a/milena/mln/fun/internal/array_base.hh b/milena/mln/fun/internal/array_base.hh index 3c7a154..3782ca4 100644 --- a/milena/mln/fun/internal/array_base.hh +++ b/milena/mln/fun/internal/array_base.hh @@ -36,6 +36,7 @@ # include <algorithm> # include <mln/core/concept/function.hh> # include <mln/util/array.hh> +# include <mln/tag/init.hh> namespace mln @@ -47,24 +48,33 @@ namespace mln namespace internal { - template <typename T> - class array_base + template <typename T, typename E> + class array_base : public Function_i2v< E > { public: + /// Returned value types + /// \{ typedef T result; - typedef metal::true_ is_mutable; + typedef typename std::vector<T>::reference mutable_result; + /// Set the function size to \p n. void resize(unsigned n); + /// Set the function size to \p n and initialize the value with + /// \p val. void resize(unsigned n, const T& val); + /// Return the number of values. unsigned size() const; - const T& operator()(unsigned i) const; - T& operator()(unsigned i); + /// Const access to the ith value. + result operator()(unsigned i) const; + /// Read-Write access to the ith value. + mutable_result operator()(unsigned i); + /// Initialize an empty function. + void init_(unsigned n); protected: - std::vector<T> v_; /// Constructors @@ -94,10 +104,8 @@ namespace mln } // end of namespace mln::fun - # ifndef MLN_INCLUDE_ONLY - /// fun::internal::array_base namespace fun @@ -106,84 +114,92 @@ namespace mln namespace internal { - template <typename T> + template <typename T, typename E> inline - array_base<T>::array_base() + array_base<T,E>::array_base() { } - template <typename T> + template <typename T, typename E> inline - array_base<T>::array_base(unsigned n) + array_base<T,E>::array_base(unsigned n) : v_(n) { } - template <typename T> + template <typename T, typename E> inline - array_base<T>::array_base(unsigned n, const T& val) + array_base<T,E>::array_base(unsigned n, const T& val) : v_(n, val) { } - template <typename T> + template <typename T, typename E> inline - array_base<T>::array_base(const util::array<T>& from) + array_base<T,E>::array_base(const util::array<T>& from) : v_(from.std_vector()) { } - template <typename T> + template <typename T, typename E> inline - array_base<T>::array_base(const std::vector<T>& from) + array_base<T,E>::array_base(const std::vector<T>& from) : v_(from) { } - template <typename T> + template <typename T, typename E> inline void - array_base<T>::resize(unsigned n) + array_base<T,E>::resize(unsigned n) { v_.resize(n); } - template <typename T> + template <typename T, typename E> inline void - array_base<T>::resize(unsigned n, const T& val) + array_base<T,E>::resize(unsigned n, const T& val) { v_.resize(n, val); } - template <typename T> + template <typename T, typename E> inline unsigned - array_base<T>::size() const + array_base<T,E>::size() const { return v_.size(); } - template <typename T> + template <typename T, typename E> inline - const T& - array_base<T>::operator()(unsigned i) const + typename array_base<T,E>::result + array_base<T,E>::operator()(unsigned i) const { mln_precondition(i < v_.size()); return v_[i]; } - template <typename T> + template <typename T, typename E> inline - T& - array_base<T>::operator()(unsigned i) + typename array_base<T,E>::mutable_result + array_base<T,E>::operator()(unsigned i) { mln_precondition(i < v_.size()); return v_[i]; } + template <typename T, typename E> + inline + void + array_base<T,E>::init_(unsigned n) + { + v_.resize(n); + } + } // end of namespace mln::fun::internal } // end of namespace mln::fun diff --git a/milena/mln/fun/l2l/relabel.hh b/milena/mln/fun/l2l/relabel.hh index b7bd7c4..0950e01 100644 --- a/milena/mln/fun/l2l/relabel.hh +++ b/milena/mln/fun/l2l/relabel.hh @@ -36,7 +36,6 @@ # include <vector> # include <algorithm> # include <mln/fun/internal/array_base.hh> -# include <mln/core/concept/function.hh> # include <mln/util/array.hh> # include <mln/metal/converts_to.hh> @@ -90,13 +89,15 @@ namespace mln { template <typename L> - class relabel : public Function_l2l< relabel<L> >, - public internal::array_base<L> + class relabel : public internal::array_base< L, relabel<L> > { - typedef internal::array_base<L> super_base_; + typedef internal::array_base< L, relabel<L> > super_base_; public: + /// Constructors + /// \{ + /// Default. relabel(); /// Constructs a function with \p nvalues. @@ -110,8 +111,8 @@ namespace mln /// Used in from_to(). Constructs that function from an std::vector. /// Always prefer using from_to instead of this constructor. relabel(const std::vector<L>& from); + /// \} - typedef metal::true_ is_mutable; }; } // end of namespace mln::fun::l2l @@ -122,6 +123,16 @@ namespace mln # ifndef MLN_INCLUDE_ONLY + // Init. + + template <typename T1, typename T2> + void init_(tag::function_t, + fun::l2l::relabel<T1>& f, + const fun::l2l::relabel<T2>& model) + { + f.init_(model.size()); + } + // convert::from_to diff --git a/milena/mln/pw/image.hh b/milena/mln/pw/image.hh index 7208ab7..75696e6 100644 --- a/milena/mln/pw/image.hh +++ b/milena/mln/pw/image.hh @@ -38,12 +38,13 @@ # include <mln/core/concept/function.hh> # include <mln/value/set.hh> # include <mln/metal/unqualif.hh> +# include <mln/metal/not_equal.hh> namespace mln { - // Fwd decl. + // Forward declaration. namespace pw { template <typename F, typename S> class image; } @@ -78,9 +79,14 @@ namespace mln // FIXME: the result type should *not* be qualified template <typename F, typename S> - struct image_< pw::image<F,S> > : default_image_< mlc_unqualif(mln_result(F)), + struct image_< pw::image<F,S> > : default_image_< mln_result(F), pw::image<F,S> > { + private: + typedef typename F::mutable_result mutable_result; + typedef mlc_not_equal(mutable_result, void) is_mutable; + + public: // misc typedef trait::image::category::primary category; typedef trait::image::speed::fast speed; @@ -93,12 +99,12 @@ namespace mln typedef trait::image::value_storage::disrupted value_storage; typedef trait::image::value_browsing::site_wise_only value_browsing; typedef trait::image::value_alignement::irrelevant value_alignement; - typedef mlc_if(typename F::is_mutable, + typedef mlc_if(is_mutable, trait::image::value_io::read_write, trait::image::value_io::read_only) value_io; // site / domain - typedef mlc_if(typename F::is_mutable, + typedef mlc_if(is_mutable, trait::image::pw_io::read_write, trait::image::pw_io::read) pw_io; typedef /* FIXME: depends on S */ undef localization; @@ -122,11 +128,16 @@ namespace mln class image : public internal::image_primary<mln_result(F), S, image<F,S> > { + typedef typename F::mutable_result mutable_result; + typedef mlc_not_equal(mutable_result, void) is_mutable; + public: /// Skeleton. typedef image< tag::function_<F>, tag::pset_<S> > skeleton; + /// Function associated type. + typedef F function_t; /// Value associated type. typedef mln_result(F) value; @@ -135,7 +146,7 @@ namespace mln typedef mln_result(F) rvalue; /// Return type of read-write access. - typedef mlc_if(typename F::is_mutable, mln_result(F)&, mln_result(F)) lvalue; + typedef mlc_if(is_mutable, mutable_result, mln_result(F)) lvalue; /// Constructor without argument. image(); @@ -153,44 +164,40 @@ namespace mln F function() const; /// Read-only access of pixel value at point site \p p. - mln_result(F) operator()(const mln_psite(S)& p) const; + rvalue operator()(const mln_psite(S)& p) const; /// Read-write access returns either a temporary value (copy) or /// a reference in the case of a mutable function (container). - lvalue operator()(const mln_psite(S)&); + lvalue operator()(const mln_psite(S)& p); }; } // end of namespace mln::pw - template <typename F, typename S> - void init_(tag::function_t, Function_v2v<F>& target, - const mln::pw::image<F,S>& model); - - template <typename F, typename S, typename J> - void init_(tag::image_t, mln::pw::image<F,S>& target, const J& model); - - - # ifndef MLN_INCLUDE_ONLY // init_ template <typename F, typename S> - void init_(tag::function_t, Function_v2v<F>& target, - const mln::pw::image<F,S>& model) + void init_(tag::function_t, F& f, const pw::image<F,S>& model) + { + f = model.function(); + } + + template <typename F1, typename F2, typename S> + void init_(tag::function_t, F1& f, const pw::image<F2,S>& model) { - target = model.function(); + init_(tag::function, f, model.function()); } template <typename F, typename S, typename J> - void init_(tag::image_t, mln::pw::image<F,S>& target, const J& model) + void init_(tag::image_t, pw::image<F,S>& target, const J& model) { F f; - init_(tag::function, f, model); + init_(tag::function, f, exact(model)); S s; - init_(tag::domain, s, model); + init_(tag::domain, s, exact(model)); target.init_(f, s); } @@ -265,7 +272,7 @@ namespace mln template <typename F, typename S> inline - mln_result(F) + typename image<F,S>::rvalue image<F,S>::operator()(const mln_psite(S)& p) const { mln_precondition(this->data_->pset_.has(p)); -- 1.5.6.5
participants (1)
-
Guillaume Lazzara