
{ //snip constructors
Hi Everybody, I'm trying to implement a proxy_iterator for ublas::matrix which should behave as an iterator over the matrix rows. My "obvious" solution does not seem to work: typedef boost::numeric::ublas::matrix<double> Matrix; typedef boost::numeric::ublas::matrix_row<Matrix> MatrixRow; typedef boost::numeric::ublas::vector<double> Vector; struct MatrixIterator: public boost::iterator_facade< MatrixIterator, Vector,//the semantic value type is a Vector boost::random_access_traversal_tag, MatrixRow//reference is a row of a matrix private: friend class boost::iterator_core_access; //snip iterating stuff //fun part MatrixRow dereference() const { return row(*m_matrix,m_element); } std::size_t m_element; Matrix* m_matrix; }; which reuslts in an error that MatrixRow can't be implicitely casted to Vector. Which is correct. At the moment I'm using a 90% hacked workaround which changes the ValueType of the Iterator to MatrixRow. This seems to work as long as I don't use algorithms which rely on the actual value_type of the iterator (for example iter_swap as implemented in the gnu libstdc++ will fail miserably even though a correct swap is implemented for the MatrixRow...different story ) Since I need std::random_shuffle I am out of luck. I tried to find the actual requirements of iterator_facade with respect to ValueType/ReferenceType in the documentation, but was not able to find them. Does someone now a solution to this problem which works and results in an iterator which can safely be used in random_shuffle? Or can point me to the correct requirements? Greetings from Germany, Oswin Krause

On Fri, Feb 24, 2012 at 12:26 AM, Oswin Krause < Oswin.Krause@ruhr-uni-bochum.de> wrote:
Hi Everybody,
I'm trying to implement a proxy_iterator for ublas::matrix which should behave as an iterator over the matrix rows.
My "obvious" solution does not seem to work:
typedef boost::numeric::ublas::matrix<double> Matrix; typedef boost::numeric::ublas::matrix_row<Matrix> MatrixRow; typedef boost::numeric::ublas::vector<double> Vector;
{ //snip constructors
struct MatrixIterator: public boost::iterator_facade< MatrixIterator, Vector,//the semantic value type is a Vector boost::random_access_traversal_tag, MatrixRow//reference is a row of a matrix private: friend class boost::iterator_core_access;
//snip iterating stuff
//fun part MatrixRow dereference() const { return row(*m_matrix,m_element); } std::size_t m_element; Matrix* m_matrix; };
which reuslts in an error that MatrixRow can't be implicitely casted to Vector. Which is correct. At the moment I'm using a 90% hacked workaround which changes the ValueType of the Iterator to MatrixRow. This seems to work as long as I don't use algorithms which rely on the actual value_type of the iterator (for example iter_swap as implemented in the gnu libstdc++ will fail miserably even though a correct swap is implemented for the MatrixRow...different story )
Since I need std::random_shuffle I am out of luck. I tried to find the actual requirements of iterator_facade with respect to ValueType/ReferenceType in the documentation, but was not able to find them. Does someone now a solution to this problem which works and results in an iterator which can safely be used in random_shuffle? Or can point me to the correct requirements?
See, for example, http://www.boost.org/doc/libs/1_48_0/libs/iterator/doc/ReadableIterator.html which states that, for a ReadableIterator i, *i must have a type convertible to the iterator's value_type. Further, for iterator_facade, the type of *i is the iterator's reference type. Therefore, reference must be convertible to value_type. Proxy references are perfectly fine, you just have to ensure they interoperate well with (i.e., are convertible to) the iterator's value_type. HTH, - Jeff

Hi, Thanks for the reply!
http://www.boost.org/doc/libs/1_48_0/libs/iterator/doc/ReadableIterator.html
which states that, for a ReadableIterator i, *i must have a type convertible to the iterator's value_type. Further, for iterator_facade, the type of *i is the iterator's reference type. Therefore, reference must be convertible to value_type.
Proxy references are perfectly fine, you just have to ensure they interoperate well with (i.e., are convertible to) the iterator's value_type.
This sounds good. So when I exchange my MatrixRow as reference type with struct MatrixRowProxy:public MatrixRow //lazyness for the example :) { operator Vector(){ return Vector(*this); } } and keep everything else untouched, like this: struct MatrixIterator: public boost::iterator_facade< MatrixIterator, Vector, boost::random_access_traversal_tag, MatrixRowProxy
{ //as before };
Everything works? That would be really nice! In this case I am happy and thank you very much for the hint to the Definition :). This helped me a lot. Greetings, Oswin

On Fri, Feb 24, 2012 at 11:15 AM, Oswin Krause < Oswin.Krause@ruhr-uni-bochum.de> wrote:
Hi,
Thanks for the reply!
http://www.boost.org/doc/libs/1_48_0/libs/iterator/doc/ReadableIterator.html
which states that, for a ReadableIterator i, *i must have a type convertible to the iterator's value_type. Further, for iterator_facade, the type of *i is the iterator's reference type. Therefore, reference must be convertible to value_type.
Proxy references are perfectly fine, you just have to ensure they interoperate well with (i.e., are convertible to) the iterator's value_type.
This sounds good.
So when I exchange my MatrixRow as reference type with
struct MatrixRowProxy:public MatrixRow //lazyness for the example :) { operator Vector(){ return Vector(*this); } }
and keep everything else untouched, like this:
struct MatrixIterator: public boost::iterator_facade< MatrixIterator, Vector, boost::random_access_traversal_tag, MatrixRowProxy
{ //as before };
Everything works? That would be really nice!
Well, the only way to be sure is to try it :) In this case I am happy and thank you very much for the hint to the
Definition :). This helped me a lot.
Great. Hopefully everything works out. Let us know if it doesn't. - Jeff

Hi,
Everything works? That would be really nice!
Well, the only way to be sure is to try it :)
In this case I am happy and thank you very much for the hint to the
Definition :). This helped me a lot.
Great. Hopefully everything works out. Let us know if it doesn't.
It doesn't :).
Because I was lazy, I just copy pasted the code and added basic
constructor & op= support to the proxy:
class MatrixRowReference:public MatrixRow{
public:
MatrixRowReference( Matrix& matrix, std::size_t i)
:MatrixRow(matrix,i){}
template<class T>
const MatrixRowReference& operator=(const T& argument){
static_cast
{...};
The error didn't change. And it is now clear to me, that conversion was
not the Problem in the first place. The quick translated and cleaned error
message reads:
/usr/include/boost/iterator/iterator_facade.hpp: In static element
function »static boost::detail::operator_arrow_result

On Sun, Feb 26, 2012 at 1:24 PM, Oswin Krause < Oswin.Krause@ruhr-uni-bochum.de> wrote:
Hi,
Everything works? That would be really nice!
Well, the only way to be sure is to try it :)
In this case I am happy and thank you very much for the hint to the
Definition :). This helped me a lot.
Great. Hopefully everything works out. Let us know if it doesn't.
It doesn't :).
Because I was lazy, I just copy pasted the code and added basic constructor & op= support to the proxy:
class MatrixRowReference:public MatrixRow{ public: MatrixRowReference( Matrix& matrix, std::size_t i) :MatrixRow(matrix,i){}
template<class T> const MatrixRowReference& operator=(const T& argument){ static_cast
(*this)=argument; return *this; } operator Vector(){ return Vector(*this); } };
so, pretty straight forward. The iterator is defined as in the previous mail with the base class:
struct ProxyIterator: public boost::iterator_facade< ProxyIterator, Vector, boost::random_access_traversal_tag, MatrixRowReference
{...};
The error didn't change. And it is now clear to me, that conversion was not the Problem in the first place. The quick translated and cleaned error message reads:
/usr/include/boost/iterator/iterator_facade.hpp: In static element function »static boost::detail::operator_arrow_result
::type boost::detail::operator_arrow_result ::make(Reference) [with ValueType = Vector, Reference = MatrixRowReference, Pointer = Vector*, boost::detail::operator_arrow_result ::type = boost::detail::operator_arrow_proxy<Vector>]«: [snipping backtrace] /usr/include/boost/iterator/iterator_facade.hpp:327:49: error: no matching function for call to »implicit_cast(MatrixRowReference*)« /usr/include/boost/iterator/iterator_facade.hpp:327:49: note: candidates are: /usr/include/boost/implicit_cast.hpp:18:10: note: template<class T> T boost::implicit_cast(typename boost::mpl::identity<T>::type) looking at the code, it apparently tried to convert MatrixRowReference* to operator_arrow_proxy<VectorType>
Checking the definition of this proxy, I'm really not sure how this should work. The compiler might try to call the constructor of operator_arrow_proxy, but this doesn't seem to be very useful, too:
template <class T> struct operator_arrow_proxy { operator_arrow_proxy(T const* px); //snip };
im quite sure, that a pointer to my proxy can't be converted to Vector*.
I am still quite certain that the error lies somewhere on my side. So, what did I do wrong?
Argh, no, that's an error in operator_array_proxy that I haven't gotten around to fixing; I've recently been added as maintainer of Iterator and I'm slowing finding time just to get up to speed on the Boost development practices. The current workaround is to provide your own arrow operator and your own version of operator_array_proxy that "does the right thing". Or locally patch Iterator. See https://svn.boost.org/trac/boost/ticket/5697 - Jeff
participants (2)
-
Jeffrey Lee Hellrung, Jr.
-
Oswin Krause