Yield from C# to C++, dealing with containers - c++

Actually, I have a design question here. Its very simple but the point is:
I have one C++ class that has a STL vector declared as a private member. But the clients of that class need to iterate over this vector.
In C# we have a very handy statement, the Yield, that in cases like that, you write a function returning an IEnumerable and it "yields" you a nice way to iterate over a private container inside that class.
I'm just trying to find an elegant solution for C++, instead of using methods like GetValue(int idx).
Any suggestions?
Example:
class Fat
{
public:
Fat();
// some code here ...
private:
void LoadSectors(SECT startPoint);
std::vector<SECT>sectors;
};
class Storage
{
public:
Storage(string CompoundFile);
//For example, this method will receive a ref to my fat system and iterate over
//the fat array in order to read every sector.
LoadStrem(Fat& fat);
};
This is far simple example.

There's no syntactic sugar in C++ analogous to yield in C#. If you want to create a class, instances of which should be iterable in the same way stock STL collections are, then you have to implement an iterator for your class, expose it as ::iterator on your type, and provide begin() and end() member functions.

You can either create an accessor function which returns a reference (or preferably const reference) to the vector, or you can create begin() and end() accessor functions which return the appropriate vector iterators.

It always hurts when you need to publish the innards of your class...
You may be able to solve it by providing algorithms as the stl does: provide a foreach function on the object's interface.
class S {
std::vector<int> v;
public:
//... and some methods to populate the vector
template< typename F > F& foreach( F& f ) {
return std::for_each( v.begin(), v.end(), f );
}
};
This way, the class remains 'closed', but you have the flexibility you need. You can also add a copy function, and maybe a transform; these are the ones I most frequently need.

Let your class expose iterators.
class Fat
{
public:
typedef std::vector<SECT>::iterator iterator;
iterator begin() { return sectors.begin(); }
iterator end() { return sectors.end(); }
Fat();
// some code here ...
private:
void LoadSectors(SECT startPoint);
std::vector<SECT>sectors;
Then the surrounding code can traverse the elements of the vector freely, through just a pair of iterators.

Related

How to hide my inner collection but allow the user iterate over him ?

I have many class that has inside list<cats> , and i want to allow users that use my class to iterate over the cats i have, so i give them access to a const iterator by writing the following function :
list<cats>::const_iterator GetIterator()
{
//return the iterator
}
Now i want to change my implementation of the class and use vector instead of list, so i need to return a const iterator of vector.
The problem is that every one that uses my class now need to change their code from list<cats>::const_iterator to vector<cat>::const_iterator.
If all the iterators where to inherit from "forward iterator" it would be very useful.
My major question is how i solve this problem, i don't want to inherit from a collection.
Another very related question is why the designers of STL chose not to inherit iterators one from another ? (for example random access iterators could have inherit from forward iterators, he have all it's functionality)
I did pretty extensive search before i asked my question but couldn't find the solution.
The closest thing i found to my question is this, but it is not exactly my question.
Give access to encapsulated container
Expose an iterator type from your class, e.g:
class a
{
vector<int> g;
public:
typdef vector<int>::const_iterator const_iterator;
const_iterator begin() const
{ return g.begin(); }
: // etc
};
If the users can recompile the code you can use
typedef list<cats> CatList;
in your include file. Then, if you want to change the container, change it to
typedef vector<cats> CatList;
and the users would use e.g.
CatList::iterator it;
However this is not a good practice; the iterators of different containers may look equal but behave differently e.g. deleting an item from a vector invalidates all iterators but doing the same on list affects only iterator of deleted item. Not mentioning the case if some day you want to use std::map<some_key,cats>.
I agree with Nim's answer and wanted to offer the style I follow which I think makes maintenance easier since now changing the underlying container type requires no work at all for users of your class and very little work for you when maintaining your class.
class A
{
// change only this to change the underlying container:
// Don't Repeat Yourself!
using container_t = std::vector<int>;
public:
// constructor from a copy of a container
A(container_t source)
: _myContainer { std::move(source) }
{}
// this derived type is part of the public interface
using const_iterator_t = container_t::const_iterator;
// following your function naming style...
const_iterator_t GetIterator() const { return /* some iterator of _myContainer */; }
const_iterator_t GetEnd() const { return std::end(_myContainer); }
private:
container_t _myContainer;
};

derive from a fancy iterator of the thrust framework (thrust::zip_iterator)

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.

C++ : Using different iterator types in subclasses without breaking the inheritance mechanism

I'm trying to achieve the following: Given an abstract class MemoryObject, that every class can inherit from, I have two subclasses: A Buffer and a BigBuffer:
template <typename T>
class MemoryObject
{
public:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
[...] //Lot of stuff
virtual iterator begin() = 0;
virtual iterator end() = 0;
};
A Buffer:
template <typename T>
class Buffer: public MemoryObject<T>
{
public:
typedef typename std::vector<T>::iterator iterator;
iterator begin() { return buffer_.begin(); }
iterator end() { return buffer_.end(); };
[...] //Lot of stuff
private:
std::vector<T> buffer_;
};
And finally:
template <typename T>
class BigBuffer: public MemoryObject<T>
{
public:
[...] //Omitted, for now
private:
std::vector<Buffer<T>*> chunks_;
};
As you can see, a BigBuffer holds a std::vector of Buffer<T>*, so you can view a BigBuffer as an aggregation of Buffer(s). Futhermore, I have a bunch of functions that must work of every MemoryObject, so this is a real signature:
template <class KernelType, typename T>
void fill(CommandQueue<KernelType>& queue, MemoryObject<T>& obj, const T& value)
{
//Do something with obj
}
What's the point? - You may ask. The point is that I must implement iterators over these classes. I've already implemented them for Buffer, and is exactly what I need: be able to iterate over a Buffer, and access to ranges (for example b.begin(), b.begin() + 50).
Obviously I can't do the same for BigBuffer, because the real data (that is inside each Buffer' private variable buffer_) is scattered accross the memory. So I need a new class, let's call it BigBufferIterator, which can overload operator like * or +, allowing me to "jump" from a memory chunk to another without incurring in in segmentation fault.
The problems are two:
The iterator type of MemoryObject is different from the iterator
type of BigBuffer: the former is a std::vector<T>::iterator, the
latter a BigBufferIterator. My compiler obviously complains
I want be able to preserve the genericity of my functions signatures
passing to them only a MemoryObject<T>&, not specializing them for
each class type.
I've tried to solve the first problem adding a template parameter classed Iterator, and giving it a default argument to each class, with a model loosely based to Alexandrescu's policy-based model. This solution solved the first issue, but not the second: my compiled still complains, telling me: "Not known conversion from BigBuffer to MemoryObject", when I try to pass a BigBuffer to a function (for example, the fill() ). This is because Iterator types are different..
I'm really sorry for this poem, but It was the only way to proper present my problem to you. I don't know why someone would even bother in reading all this stuff, but I'll take pot luck.
Thanks in advance, only just for having read till this point.
Humbly,
Alfredo
They way to go is to use the most general definition as the iterator type of the base. That is, you want to treat the data in a Buffer as just one segment while the BigBuffer is a sequence of the corresponding segments. This is a bit unfortunate because it means that you treat your iterator for the single buffer in Buffer as if it may be multiple buffers, i.e. you have a segmented structure with just one segment. However, compared to the alternative (i.e. a hierarchy of iterators with virtual functions wrapped by a handle giving value semantics to this mess) you are actually not paying to bad a cost.
I encountered the same problem in a different context; let me restate it.
You have a Base class (which could be abstract), which is iterable via its BaseIterator.
You have a Child subclass, which differs in implementation slightly, and for which you have a different specialized ChildIterator.
You have custom functions that work with Base, and rely on its iterability.
It is not feasible to generate a template specialization of the custom functions for each subclass of Base. Possible reasons may be:
huge code duplication;
you distribute this code as a library and other developers are going to subclass Base;
other classes will take some reference or pointer to Base and apply those custom functions, or more generically:
Base implements some logic that is going to be uses in contexts where do not know any of the subclasses (and writing completely templated code is too cumbersome).
Edit: Another possibility would be using type erasure. You would hide the real iterator that you're using behind a class of a fixed type. You would have to pay the cost of the virtual functions call though. Here is an implementation of a any_iterator class which implements exactly iterator type erasure, and some more background on it.
The only effective solution I could find was to write a multi-purpose iterator that can iterate over all possible containers, possibly exploiting their internals (to avoid copy-pasting the iterator code for every subclass of Base):
// A bigger unit of memory
struct Buffer;
class Iterator {
// This allows you to know which set of methods you need to call
enum {
small_chunks,
big_chunks
} const _granularity;
// Merge the data into a union to save memory
union {
// Data you need to know to iterate over ints
struct {
std::vector<int> const *v;
std::vector<int>::const_iterator it;
} _small_chunks;
// Data you need to know to iterate over buffer chunks
struct {
std::vector<Buffer *> const *v;
std::vector<Buffer *>::const_iterator it;
} _big_chunks;
};
// Every method will have to choose what to do
void increment() {
switch (_granularity) {
case small_chunks:
_small_chunks.it++;
break;
case big_chunks:
_big_chunks.it++;
break;
}
}
public:
// Cctors are almost identical, but different overloads choose
// different granularity
Iterator(std::vector<int> const &container)
: _granularity(small_chunks) // SMALL
{
_small_chunks.v = &container;
_small_chunks.it = container.begin();
}
Iterator(std::vector<Buffer *> const &container)
: _granularity(big_chunks) // BIG
{
_big_chunks.v = &container;
_big_chunks.it = container.begin();
}
// ... Implement all your methods
};
You can use the same class for both Base and Child, but you need to initialize it differently. At this point you can make begin and end virtual and return an Iterator constructed differently in each subclass:
class Base {
public:
virtual Iterator begin() const = 0;
};
class IntChild : public Base {
std::vector<int> _small_mem;
public:
virtual Iterator begin() const {
// Created with granularity 'small_chunks'
return Iterator(_small_mem);
}
// ...
};
class BufferChild : public Base {
std::vector<Buffer *> _big_mem;
public:
virtual Iterator begin() const {
// Created with granularity 'big_chunks'
return Iterator(_big_mem);
}
// ...
};
You will pay a small price in performance (because of the switch statements) and in code duplication, but you will be able to use any generic algorithm from <algorithm>, to use range-loop, to use Base only in every function, and it's not stretching the inheritance mechanism.
// Anywhere, just by knowing Base:
void count_free_chunks(Base &mem) {
// Thanks to polymorphism, this code will always work
// with the right chunk size
for (auto const &item : mem) {
// ...this works
}
// This also works:
return std::count(mem.begin(), mem.end(), 0);
}
Note that the key point here is that begin() and end() must return the same type. The only exception would be if Child's methods would shadow Base's method (which is in general not a good practice).
One possible idea would be to declare an abstract iterator, but this is not so good. You would have to use all the time a reference to the iterator. Iterator though are supposed to be carried around as lightweight types, to be assignable and easily constructible, so it would make coding a minefield.

Nested class definition in Abstract Base Class (C++)

Are there any suggestions on how to use a nested class iterator
in an ABC in C++ ? Note that, I also want to have a virtual function returning an
instance of this class.
More specifically here's my approach:
class ABC {
typedef iterator<forward_iterator_tag, MyType> MyTypeIter;
virtual MyTypeIter *begin() = 0;
};
class Foo : ABC {
MyTypeIter : public ABC::MyTypeIter;
virtual MyTypeIter *begin();
};
ABC::MyTypeIter *Foo::begin()
{
Foo::MyTypeIter *ret;
ret = new Foo::MyTypeIter(...);
return ret;
}
Is there a better approach than this (e.g. one that does not use pointers) ?
What is your problem? A nested class behaves the same way as a top-level class, so you may return its objects just as you would have returned any other.
Take a look on how iterators are implemented for std::vector class, for example.
I prefer to keep iterators interal to the class and exposing only an interface for iteration.
For example, you can implement a List<> with the methods:
void prepare_iteration() // reset the internal iterator
bool step_iteration() // move internal iterator
DATA_TYPE & read() // return the data by using the iterator
write( DATA_TYPE & ) // update the data by using the iterator
In this example the iterator can be a simple node pointer and it's never exposed to the user.
I find this approach much easier and safer than iterator objects.(well the 'safer' part needs a lot of discussion)
The above interface can be implemented as an abstract class.
Your container (or whatever) classes can inherit it and implement it.
I know that's not the answer that you are looking for but it's just an alternative idea to design your classes.

Returning an 'any kind of input iterator' instead of a vector::iterator or a list::iterator [duplicate]

This question already has answers here:
Generic iterator
(3 answers)
Closed 8 years ago.
Suppose I want to implement in C++ a data-structure to store oriented graphs. Arcs will be stored in Nodes thanks to STL containers. I'd like users to be able to iterate over the arcs of a node, in an STL-like way.
The issue I have is that I don't want to expose in the Node class (that will actually be an abstract base class) which STL container I will actually use in the concrete class. I therefore don't want to have my methods return std::list::iterator or std::vector::iterator...
I tried this:
class Arc;
typedef std::iterator<std::random_access_iterator_tag, Arc*> ArcIterator; // Wrong!
class Node {
public:
ArcIterator incomingArcsBegin() const {
return _incomingArcs.begin();
}
private:
std::vector<Arc*> _incomingArcs;
};
But this is not correct because a vector::const_iterator can't be used to create an ArcIterator. So what can be this ArcIterator?
I found this paper about Custom Iterators for the STL but it did not help. I must be a bit heavy today... ;)
Try this:
class Arc;
class Node {
private:
std::vector<Arc*> incoming_;
public:
typedef std::vector<Arc*>::iterator iterator;
iterator incoming_arcs_begin()
{ return incoming_.begin(); }
};
And use Node::iterator in the rest of the code. When/if you change the container, you have to change the typedef in a single place. (You could take this one step further with additional typedef for the storage, in this case vector.)
As for the const issue, either define vector's const_iterator to be your iterator, or define double iterator types (const and non-const version) as vector does.
Have a look at Adobe's any_iterator: this class uses a technique called type erase by which the underyling iterator type is hidden behind an abstract interface. Beware: the use of any_iterator incurs a runtime penalty due to virtual dispatching.
I want to think there should be a way to do this through straight STL, similar to what you are trying to do.
If not, you may want to look into using boost's iterator facades and adaptors where you can define your own iterators or adapt other objects into iterators.
To hide the fact that your iterators are based on std::vector<Arc*>::iterator you need an iterator class that delegates to std::vector<Arc*>::iterator. std::iterator does not do this.
If you look at the header files in your compiler's C++ standard library, you may find that std::iterator isn't very useful on its own, unless all you need is a class that defines typedefs for iterator_category, value_type, etc.
As Doug T. mentioned in his answer, the boost library has classes that make it easier to write iterators. In particular, boost::indirect_iterator might be helpful if you want your iterators to return an Arc when dereferenced instead of an Arc*.
Consider using the Visitor Pattern and inverting the relationship: instead of asking the graph structure for a container of data, you give the graph a functor and let the graph apply that functor to its data.
The visitor pattern is a commonly used pattern on graphs, check out boost's graph library documentation on visitors concepts.
If you really don't want the client's of that class to know that it uses a vector underneath, but still want them to be able to somehow iterate over it, you most likely will need to create a class that forwards all its methods to std::vector::iterator.
An alternative would be to templatize Node based on the type of container it should use underneath. Then the clients specifically know what type of container it is using because they told them to use it.
Personally I don't think it usually makes sense to encapsulate the vector away from the user, but still provide most (or even some) of its interface. Its too thin of an encapsulation layer to really provide any benefit.
I looked in the header file VECTOR.
vector<Arc*>::const_iterator
is a typedef for
allocator<Arc*>::const_pointer
Could that be your ArcIterator? Like:
typedef allocator<Arc*>::const_pointer ArcIterator;
You could templatize the Node class, and typedef both iterator and const_iterator in it.
For example:
class Arc {};
template<
template<class T, class U> class Container = std::vector,
class Allocator = std::allocator<Arc*>
>
class Node
{
public:
typedef typename Container<Arc*, Allocator>::iterator ArcIterator;
typedef typename Container<Arc*, Allocator>::Const_iterator constArcIterator;
constArcIterator incomingArcsBegin() const {
return _incomingArcs.begin();
}
ArcIterator incomingArcsBegin() {
return _incomingArcs.begin();
}
private:
Container<Arc*, Allocator> _incomingArcs;
};
I haven't tried this code, but it gives you the idea. However, you have to notice that using a ConstArcIterator will just disallow the modification of the pointer to the Arc, not the modification of the Arc itself (through non-const methods for example).
C++0x will allow you do this with automatic type determination.
In the new standard, this
for (vector::const_iterator itr = myvec.begin(); itr != myvec.end(); ++itr
can be replaced with this
for (auto itr = myvec.begin(); itr != myvec.end(); ++itr)
By the same token, you will be able to return whatever iterator is appropriate, and store it in an auto variable.
Until the new standard kicks in, you would have to either templatize your class, or provide an abstract interface to access the elements of your list/vector. For instance, you can do that by storing an iterator in member variable, and provide member functions, like begin() and next(). This, of course, would mean that only one loop at a time can safely iterate over your elements.
Well because std::vector is guaranteed to have contiguous storage, it should be perfect fine to do this:
class Arc;
typedef Arc* ArcIterator;
class Node {
public:
ArcIterator incomingArcsBegin() const {
return &_incomingArcs[0]
}
ArcIterator incomingArcsEnd() const {
return &_incomingArcs[_incomingArcs.size()]
}
private:
std::vector<Arc*> _incomingArcs;
};
Basically, pointers function enough like random access iterators that they are a sufficient replacement.