What is the canonical way to derive from one of the fancy iterators of the thrust framework?
I'm storing 3D points in a structure of arrays. Now I was thinking about a convenient way to get a blas vector type from that. What I came up with was something like this:
namespace abc {
typedef VERY_BASIC_LINEAR_ALGEBRA_VECTOR_CLASS_FOR_TESTING t_vector;
typedef typename thrust::device_vector::iterator t_baseIterator;
typedef typename thrust::tuple<t_baseIterator,t_baseIterator,t_baseIterator> t_iteratorTuple;
typedef typename thrust::zip_iterator<t_iteratorTuple> t_zipIterator;
struct custom_iterator: public t_zipIterator {
custom_iterator(t_zipIterator zi): t_zipIterator(zi) {}
t_vector getVector() {
return t_vector(**this);
}
void setVector(const t_vector& v) {
**this = (t_tuple)v;
}
};
}
This works. Which means I can do something like it.getVector()
(where it
is a valid custom_iterator), and pass this custom_iterators to thrusts compute primitives, like transform_reduce.
I've searched a little bit more about the documentation of thrust and found thrust::iterator_adaptor
. Now the question: should one rather use iterator_adaptor
? If so, why? What are the pros and cons of above piece of code. It seems rather exaggerated using iterator_adaptor
:
#include <thrust/iterator/iterator_adaptor.h>
class custom_iterator: public thrust::iterator_adaptor<custom_iterator, t_zipIterator> {
public:
typedef thrust::iterator_adaptor<custom_iterator, t_zipIterator> super_t;
custom_iterator(const t_zipIterator &zi) : super_t(zi) {}
t_vector getVector() {
return t_vector(**this);
}
void setVector(const t_vector& v) {
**this = (t_tuple)v;
}
friend class thrust::iterator_core_access;
};
I don't know if this works, as I didn't try.
So the question is: What is the canonical way doing this?
Related to this is another question: A functor used by thrust::transform_reduce or thrust::transform_iterator must accept the underlying type of a given iterator, not the iterator itself. So above custom_iterator is pretty much useless. Is there a way to accept an iterator instead of an dereferenced iterator in the operator() member function of the used functor?
You may ask yourself why I want a derived iterator with this additonal getters and setters, as above examples suggest that t_vector
is initialised with the underling tuple of the zip_iterator anyway. But this is only an example, and there is a more complex case, where above concept would be a very convenient way to go.
As I couldn't find a virtual destructor neither in thrust::zip_iterator
nor in thrust::iterator_adaptor
, I guess it's a bad idea to derive from either one.