* 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(a)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(a)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