Wrapping STL in order to extend - c++

So I read that inheritance from STL is a bad idea. But what about wrapping STL classes inside other classes in order to extend them. This with the main purpose of separating levels of abstraction, among other things.
Something like:
template<class T>
class MyVector{
public:
T& last(){
return data[data.size() - 1]
}
bool include(T& element);
//etc.
private:
vector<T> data;
}
Is this a good idea? Is this something c++ programmers do often?
Thank you.

Yes, wrapping is better than inheritance, but only if you need to add state to an existing data structure. Otherwise, add non-member functions. This is explained in more detail in item 35 of C++ Coding Standards (Amazon)
To add state, prefer composition instead of inheritance. Admittedly, it's tedious to have to write passthrough functions for the member functions
you want to keep, but such an implementation is vastly better and safer than
using public or nonpublic inheritance.
template<typename T>
class MyExtendedVector
{
public:
// pass-through functions for std::vector members
void some_existing_fun() { return vec_.some_existing_fun(); }
// new functionality that uses extra state
void some_new_fun() { // your implementation here }
private:
std::vector<T> vec_;
// extra state e.g. to do logging, caching, or whatever
};
To add behavior, prefer to add nonmem-ber functions instead of member
functions.
However make sure to make your algorithms as generic as possible:
// if you CAN: write algorithm that uses iterators only
// (and delegates to iterator category that container supports)
template<typename Iterator, typename T>
bool generic_contains(Iterator first, Iterator last, T const& elem)
{
// implement using iterators + STL algorithms only
return std::find(first, last, elem) != last;
}
// if you MUST: write algorithm that uses specific interface of container
template<typename T>
void vector_contains(std::vector<T> const& v, T const& elem)
{
// implement using public interface of Container + STL algorithms
return generic_contains(v.begin(), v.end(), elem);
}

I can only speak for myself but I haven't done this, and I probably wouldn't suggest it in general.
In almost every case an iterator-based algorithm is simpler to implement and separates the algorithm from the container. For example, assuming that your include method is simply to determine if an element is in the vector you would use either find, binary_search, or lower_bound depending on your container's contents and search needs.
Occasionally I have implemented a class that looks like a container to the outside world by providing begin/end methods. In this case it sometimes does have a standard container underlying, but you only implement a minimal public interface to represent what your class actually models.

I would avoid doing this, as the last person replied. I understand where you are going where you want your container to wrap some of the more complex operations into simplier methods and are thinking that you could change the underlying container at some point without having to change your interfaces. However, having said that, your object should model your business requirements and then the implementation of those objects would use whatever data container and access patterns are best. I guess what I am saying is that you won't end up re-using this new vector class as the data access of your business requirements will be different each time and you will use a some standard generic container like std::vector again and the iterator based algos to access the data.
Now if there is some algo that doesn't exist, you can write that iterator based algo for that specific project and then keep that algo code which you may be able to re-use. Below shows a set grep algo that I wrote that was based on a set intersection but wasn't doing exactly what I wanted. I could reuse this algo another time.
#include <utility>
#include <algorithm>
// this is a set grep meaning any items that are in set one
// will be pulled out if they match anything in set 2 based on operator pred
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
_OutputIterator
setGrep(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result, _Compare __comp)
{
while (__first1 != __last1 && __first2 != __last2)
if (__comp(*__first1, *__first2))
++__first1;
else if (__comp(*__first2, *__first1))
++__first2;
else
{
*__result = *__first1;
++__first1;
++__result;
}
return __result;
}

Related

C++/STL public iterators for deeply nested private data

Consider the below class definition featuring deeply nested private data.
template <typename T, typename U, typename V>
class NestedData {
private:
typedef std::vector<V> L3;
typedef std::map<U, L3> L2;
typedef std::map<T, L2> L1;
L1 inner_data;
};
Suppose we wish to add a public interface to iterate over each of the three levels. That is, we want to allow the client to build three nested loops that iterate over each value of type V, knowing the associated values of types U and T. We could add the below methods:
L1::const_iterator begin() const { return inner_data.begin(); }
L1::const_iterator end() const { return inner_data.end(); }
In this case, the results from the iterator would be pairs, with the right side being referenced to type L2. Although the reference is const, it exposes the full API of the std::map type, which is undesirable for a public interface. A cleaner solution would offer only a wrapper to makes it possible to iterate over L2. However, I have not seen any standard idioms for this kind of encapsulation of STL containers, and even the best case, implementation of a solution seems to create a high degree of code bloat.
What would be a common solution to this issue that plays well with general C++ conventions?
Just expose the map itself through const getter. Exposing the iterator still binds your users to the underlying datatype, but it's crippling them - for example, they can't use find on it - so there is a drawback without any benefit.
If you can redesign your class in such a way that inner map fully becomes an implementation detail, and clients would never need to see it - than you will remove iterators and setters, and expose some meaningful functions instead.
I would create a custom iterator that would provide the T, U, V values as you iterate. This would completely insulate your user from the implementation details of your data. If you truly need nested type logic. Then I would use a custom iterator that returned an adapter object that would return the final iterator to the list.

What is the base class for STL containers list, deque, vector etc.?

I want to write a function that can take either of STL generic list, deque or vector and search for a key in it. What would be method signature of this function and how can we implement it?
What I know is that if we are accepting any of the derived classes in function argument we can use base abstract class assuming all relevant derived ones have the functions you need for your question.
EDIT: We cannot pass container's iterators in the function argument. If we can that is easy. It has to be a container.
I was thinking: Assuming 'Container' is an abstract base class from STL containers (which its not, according to first answer below).
template
bool Search(std::Container C, T& key);
Thanks
As SergeyA mentioned in his answer, C++'s STL does not have polymorphic containers (opposing to Java or C# interfaces).
Regarding your requested function signature, look into STL <algorithm> header. There are lot of functions operating on some data, using two pointers (iterators) to the beginning and end of data block. For example,
template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );
searching for some value in [first, last).
If you really want to pass whole container to the function, you'll similarly write
template<class Container, class T>
bool Search(const Container& container, const T& value)
{
for (auto iterator = container.begin(); iterator != container.end(); ++iterator)
{
if (*iterator == value)
return true;
}
return false;
}
Luckily for us, there is no base class for standard library containers. The only place I know of where polymorphic inheritance is used in standard library is streams, and this is what earned them such a bad fame.
Standard containers are non-polymorphic, thus fast. You will have to make your function template to work with any container.
For example,
template <class CONTAINER> bool exists(const CONTAINER& ctr, const typename CONTAINER::value_type& key);
Containers do not have base classes. They do not define an interface based on dynamic polymorphism. They define an interface based on static polymorphism. That is, they do implement certain methods in common, but they are not inherited from some prototype.
Therefore, you must use the standard C++ mechanism for static polymorphism: templates. The container itself must be a template parameter:
template<typename Container, ...>
bool IsFound(const Container &c, ...);
Of course, this will not prevent any user from passing types which are not vector, deque, or list. They could pass anything that fulfills the implicit static requirements that your IsFound function imposes.
You could pass a set for example, and it would probably work, to some degree. But it wouldn't be nearly as fast as calling set::find with the type.

Polymorphic converting iterator

Consider the following (simplified) scenario:
class edgeOne {
private:
...
public:
int startNode();
int endNode();
};
class containerOne {
private:
std::vector<edgeOne> _edges;
public:
std::vector<edgeOne>::const_iterator edgesBegin(){
return _edges.begin();
};
std::vector<edgeOne>::const_iterator edgesEnd(){
return _edges.end();
};
};
class edgeTwo {
private:
...
public:
int startNode();
int endNode();
};
class containerTwo {
private:
std::vector<edgeTwo> _edges;
public:
std::vector<edgeTwo>::const_iterator edgesBegin(){
return _edges.begin();
};
std::vector<edgeTwo>::const_iterator edgesEnd(){
return _edges.end();
};
};
I.e., I have two mostly identical edge types and two mostly identical container types. I can iterate over each kind individually. So far, so fine.
But now my use case is the following: Based on some criteria, I get either a containerOne or a containerTwo object. I need to iterate over the edges. But because the types are different, I cannot easily do so without code duplication.
So my idea is the following: I want to have an iterator with the following properties:
- Regarding its traversal behavior, it behaves either like a std::vector<edgeOne>::const_iterator or a std::vector<edgeTwo>::const_iterator, depending on how it was initialized.
- Instead of returning a const edgeOne & or const edgeTwo &, operator* should return a std::pair<int,int>, i.e., apply a conversion.
I found the Boost.Iterator Library, in particular:
iterator_facade, which helps to build a standard-conforming iterator and
transform_iterator, which could be used to transform edgeOne and edgeTwo to std::pair<int,int>,
but I am not completely sure how the complete solution should look like. If I build nearly the entire iterator myself, is there any benefit to use transform_iterator, or will it just make the solution more heavy-weight?
I guess the iterator only needs to store the following data:
A flag (bool would be sufficient for the moment, but probably an enum value is easier to extend if necessary) indicating whether the value type is edgeOne or edgeTwo.
A union with entries for both iterator types (where only the one that matches the flag will ever be accessed).
Anything else can be computed on-the-fly.
I wonder if there is an existing solution for this polymorphic behavior, i.e. an iterator implementation combining two (or more) underlying iterator implementation with the same value type. If such a thing exists, I could use it to just combine two transform_iterators.
Dispatching (i.e., deciding whether a containerOne or a containerTwo object needs to be accessed) could easily be done by a freestanding function ...
Any thoughts or suggestions regarding this issue?
How about making your edgeOne & edgeTwo polymorphic ? and using pointers in containers ?
class edge
class edgeOne : public edge
class edgeTwo : public edge
std::vector<edge*>
Based on some criteria, I get either a containerOne or a containerTwo object. I need to iterate over the edges. But because the types are different, I cannot easily do so without code duplication.
By "code duplication", do you mean source code or object code? Is there some reason to go past a simple template? If you're concerned about the two template instantiations constituting "code duplicaton" you can move most of the processing to an out-of-line non-templated do_whatever_with(int, int) support function....
template <typename Container>
void iterator_and_process_edges(const Container& c)
{
for (auto i = c.edgesBegin(); i != c.edgesEnd(); ++i)
do_whatever_with(i->startNode(), i->endNode());
}
if (criteria)
iterate_and_process_edges(getContainerOne());
else
iterate_and_process_edges(getContainerTwo());
My original aim was to hide the dispatching functionality from the code that just needs to access the start and end node. The dispatching is generic, whereas what happens inside the loop is not, so IMO this is a good reason to separate both.
Not sure I follow you there, but I'm trying. So, "code that just needs to access the start and end node". It's not clear whether by access you mean to get startNode and endNode for a container element, or to use those values. I'd already factored out a do_whatever_with function that used them, so by elimination your request appears to want to isolate the code extracting the nodes from an Edge - done below in a functor:
template <typename Edge>
struct Processor
{
void operator()(Edge& edge) const
{
do_whatever_with(edge.startNode(), edge.endNode());
}
};
That functor can then be applied to each node in the Container:
template <typename Container, class Processor>
void visit(const Container& c, const Processor& processor)
{
for (auto i = c.edgesBegin(); i != c.edgesEnd(); ++i)
processor(*i);
}
"hide the dispatching functionality from the code that just needs to access the start and end node" - seems to me there are various levels of dispatching - on the basis of criteria, then on the basis of iteration (every layer of function call is a "dispatch" in one sense) but again by elimination I assume it's the isolation of the iteration as above that you're after.
if (criteria)
visit(getContainerOne(), Process<EdgeOne>());
else
visit(getContainerTwo(), Process<EdgeTwo>());
The dispatching is generic, whereas what happens inside the loop is not, so IMO this is a good reason to separate both.
Can't say I agree with you, but then it depends whether you can see any maintenance issue with my first approach (looks dirt simple to me - a layer less than this latest incarnation and considerably less fiddly), or some potential for reuse. The visit implementation above is intended to be reusable, but reusing a single for-loop (that would simplify further if you have C++11) isn't useful IMHO.
Are you more comfortable with this modularisation, or am I misunderstanding your needs entirely somehow?
template<typename T1, typename T2>
boost::variant<T1*, T2*> get_nth( boost::variant< std::vector<T1>::iterator, std::vector<T2>::iterator > begin, std::size_t n ) {
// get either a T1 or a T2 from whichever vector you actually have a pointer to
}
// implement this using boost::iterator utilities, I think fascade might be the right one
// This takes a function that takes an index, and returns the nth element. It compares for
// equality based on index, and moves position based on index:
template<typename Lambda>
struct generator_iterator {
std::size_t index;
Lambda f;
};
template<typename Lambda>
generator_iterator< typename std::decay<Lambda>::type > make_generator_iterator( Lambda&&, std::size_t index=0 );
boost::variant< it1, it2 > begin; // set this to either one of the begins
auto double_begin = make_generator_iterator( [begin](std::size_t n){return get_nth( begin, n );} );
auto double_end = double_begin + number_of_elements; // where number_of_elements is how big the container we are type-erasing
Now we have an iterator that can iterate over one, or the other, and returns a boost::variant<T1*, T2*>.
We can then write a helper function that uses a visitor to extract the two fields you want from the returned variant, and treat it like an ADT. If you dislike ADTs, you can instead write up a class that wraps the variant and provides methods, or even change the get_nth to be less generic and instead return a struct with your data already produced.
There is going to be the equivalent of a branch on each access, but there is no virtual function overhead in this plan. It does currently requires an auto typed variable, but you can write an explicit functor to replace the lambda [begin](std::size_t n){return get_nth( begin, n );} and even that issue goes away.
Easier solutions:
Write a for_each function that iterates over each of the containers, and passes in the processed data to the passed in function.
struct simple_data { int x,y; };
std::function<std::function<void(simple_data)>> for_each() const {
auto begin = _edges.begin();
auto end = _edges.end();
return [begin,end](std::function<void(simple_data)> f) {
for(auto it = begin; it != end; ++it) {
simple_data d;
d.x = it->getX();
d.y = it->getY();
f(d);
}
};
};
and similar in the other. We now can iterate over the contents without caring about the details by calling foo->foreach()( [&](simple_data d) { /*code*/ } );, and because I stuffed the foreach into a std::function return value instead of doing it directly, we can pass the concept of looping around to another function.
As mentioned in comments, other solutions can include using boost's type-erased iterator wrappers, or writing a python-style generator mutable generator that returns either a simple_data. You could also directly use the boost iterator-creation functions to create an iterator over boost::variant<T1, T2>.

How do I apply the DRY principle to iterators in C++? (iterator, const_iterator, reverse_iterator, const_reverse_iterator)

OK, so I have two (completely unrelated, different project) classes using iterators now. One has iterator and reverse_iterator working as intended, and the other, current one has iterator and a semi-broken const_iterator (specifically, because const_iterator derives from iterator, the code LinkedList<int>::iterator i = const_list.begin() is valid and allows you to modify the const defined list...).
I intend to add all four types to this class... If I can.
How would I proceed to minimize copy/pasting code and changing only the return type? Create a base class like base_iterator to inherit from? Create an iterator or const_iterator and inherit from that? Inherit from some std:: class? If any of these cases are the "best" approach, what code goes where?
Perhaps none of the alternatives are good? I'm quite lost here, and can't find much reference material.
Any advice is appreciated, but please keep in mind that I'm new to the subject (both iterators and C++ in general, especially OOP). I've tried, in vain, to study the header files shipped with GCC - they're not exactly the tutorial I'm looking for.
Sometimes, blanket application of the so-called DRY rule (Don't Repeat Yourself, for those who aren't familiar) is not the best approach. Especially if you're new to the language (C++ and iterators) and OOP itself (methodology), there's little benefit in trying to minimise the amount of code you need to write right now.
I would implement the two iterators using appropriate code for each of them. Perhaps after you have more experience with the language, tools, and techniques, then go back and see whether you can reduce the amount of code by factoring out common code.
It's actually extremely simple.
First of all, take a look at Boost.Iterator library.
Second: you need to declare a base class (it's well explained in the example how to proceed) that will be similar to this one.
template <class Value>
class BaseIterator: boost::iterator_adaptor< ... > {};
You implement the operations to move your pointer around there. Note that because it's an adaptation over an already existing iterator, you can implement it with only a few strokes. It's really impressive.
Third, you simply typedef it with the const and non-const versions:
typedef BaseIterator<Value> iterator;
typedef BaseIterator<const Value> const_iterator;
The library explictly show you how to make the const_iterator version be constructible from the iterator version.
Fourth, for the reverse thing, there is a special reverse_iterator object, that is built on a regular iterator and move backwards :)
All in all, a really elegant and yet fully functional way of defining iterators on custom classes.
I regularly write my own container adaptors, and it's less about DRY than simply saving myself some typing!
Make iterator derive from const_iterator instead of the other way around. Use const_cast appropriately (as an implementation detail, unexposed to users). This works very well in the simple cases and models that "iterators are const_iterators" directly.
When this starts to require clarification comments in your code, then write separate classes. You can use localized macros to generate similar code for you, to avoid repeating the logic:
struct Container {
#define G(This) \
This& operator++() { ++_internal_member; return *this; } \
This operator++(int) { This copy (*this); ++*this; return copy; }
struct iterator {
G(iterator)
};
struct const_iterator {
G(const_iterator)
const_iterator(iterator); // and other const_iterator specific code
};
#undef G
};
That the macro is scoped/localized is important, and, of course, only use it if it actually helps you—if it results in less readable code for you, type it out explicitly.
And about reverse iterators: you can use std::reverse_iterator to wrap your "normal" iterators in many cases, instead of rewriting them.
struct Container {
struct iterator {/*...*/};
struct const_iterator {/*...*/};
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
};
LinkedList<int>::iterator i = const_list.begin() What does your begin method look like? By studying the STL you can see that containers define two such methods with the following signatures:
const_iterator begin() const;
iterator begin();
You should not have a problem getting an iterator from an object qualified as const. I don't think DRY applies here.
Once I used the following approach:
make a template class common_iterator
add typedefs for "iterator" and "const_iterator"
add to "common_iterator" a constructor taking "iterator" type
For "iterator" the additional constructor will replace default copy constructor, in my case it was equivalent to default copy constructor.
For "const_iterator" it will be an additional constructor which allows to construct "const_iterator" from "iterator"
A more concrete version of what maxim1000 suggested:
#include <type_traits>
template<typename Container, bool forward>
class iterator_base
{
public:
using value_type =
typename std::conditional<std::is_const<Container>::value,
const typename Container::value_type,
typename Container::value_type>::type;
iterator_base() { }
// For conversions from iterator to const_iterator.
template<typename U>
iterator_base(const iterator_base<U, forward>& other)
: c(other.c)
{
// ....
}
value_type& operator*() const
{
// ...
}
iterator_base& operator++()
{
if (forward)
{
// ...
}
else
{
// ...
}
}
iterator_base& operator++(int)
{
iterator_base copy(*this);
++*this;
return copy;
}
private:
Container* c = nullptr;
// ...
};
using iterator = iterator_base<self_type, true>;
using const_iterator = iterator_base<const self_type, true>;
using reverse_iterator = iterator_base<self_type, false>;
using const_reverse_iterator = iterator_base<const self_type, false>;

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.