container iterators - should they be nested? - c++

Should the custom iterator for a customer container be a nested class or a free(for a lack of better word) class? I have seen it both ways, especially in books and online, so not sure if one approach has advantage over other. The two books I am using both have the iterators defined as free classes where as online first few implementations I checked, all were nested.
I personally prefer nested iterator, if the iterator only serves a particular container.
Thanks,
DDG
p.s. - The question is not about preference but about advantages of one approach over others.

the iterator only serves a particular container.
The main thing to know is how true this will be.
Depends on the amount of types of containers you will define and the implementations you are applying, it's quite possible for some of them using the exact same type of iterator.
For instance, you will likely find myArray::iterator and myVector::iterator have the exact same implementation. Similarly, mySet::iterator and myMap::iterator might be the same as well.
If that's the case, it might be better do something like this to avoid implementing the same iterator multiple times:
// iterators.h
template<typename T>
struct contiguous_iterator
{
// implementation for array and set iterator
};
template<typename T>
struct rb_tree_iterator
{
// implementation for set and map iterator
};
// contiguous_containers.h
template<typename T>
struct myArray
{
using iterator = contiguous_iterator<T>;
//...
};
// rb_tree_containers.h
template<typename Key, typename Value>
struct myMap
{
using iterator = rb_tree_iterator<tuple<Key, Value>>;
//...
};

The fact is that an iterator, it is built and used for a specific class, so there is no need for it to be defined outside. Since you only use it in coordination with your container.
Different thing if your iterator it is used by different classes, but I can't really find an example of where it could be useful.
Edit. Finally, to wrap up, both can be done and I don't think there are any advantages in terms of memory used or execution times. For a better understanding of this we should check difference between a nested class and a not-nested class, but I think is off-topic here.

While there would be no definitive answer,
I prefer to define them outside.
And I disagree with ranghetto's claim
The fact is that an iterator, it is built and used for a specific class
Different thing if your iterator it is used by different classes, but I can't really find an example of where it could be useful.
I implemented std::vector-like containers(notice plural form), including double-ended one, small-buffer optimized one, etc..
And they use same iterator implementation.
In general, defining iterators outside reduces unnecessary dependencies.

Related

Setting vector as a general parameter

So I've been trying to create a function that will receive vector objects as a general type in C++.
I have three classes Coffee, Snack, and Juice. And I have a binary search function to search for a specific item in each of the three vector objects created by those classes. But in order to do the binary search, I'd have to define three binary search functions. For example, binarySearchCoffee(vector coffeeList), binarySearchSnack(vector coffeeList) and the same for the Juice. So, is there a way to create a general vector type parameter that will take in whatever I inserted or is defining three functions ordinary? But I do not think so because it violates the DRY rule.
Thank you for your time.
This is what templates are for. Indeed, that's how the vector itself works!!
template <typename ElementType>
bool DoMyBinarySearch(const std::vector<ElementType>& container, const ElementType& value)
{
auto it = std::lower_bound(std::begin(container), std::end(container), value);
return it != std::end(container) && *it == value;
}
You might even consider making the container type the template argument, so that you're not restricted to vectors (though that may not be useful in this case).
This example also doesn't consider alternative allocators, or alternative comparators, which may or may not matter to you. cppreference.com's std::lower_bound article has a more robust example.
Don't forget to document the precondition that container must be sorted.

Compile time triggered range check for std::vector

The goal:
I would like to have a range checked version of std::vector's operator [] for my debug builds and no range check in release mode.
The range check in debug mode is obviously good for debugging, but it causes a slowdown of 5% - 10% in my release code which I would like to avoid.
Possible solutions:
I found a solution in Stroustrup's "The C++ programming language". He did the following:
template <class T>
class checked_vector : public std::vector<T> {
public:
using std::vector<T>::vector;
//override operator [] with at()
};
This is problematic because it inherits from a class with non-virtual destructor which is dangerous. (And the Lounge was not too fond of that solution.)
Another idea would be a class like this:
template <class T>
class checked_vector {
std::vector<T> data_;
public:
//put all public methods of std::vector here by hand
};
This would be both tedious and create a large amount of copy-paste which is bad too.
The nice thing about both the above solutions is that I can simply toggle them on and off with a macro definition in my makefile.
The questions:
Is there a better solution? (If not, why not?)
If not, is one of the above considered acceptable? (I know this one is opinion based, please focus on No. 1 if possible.)
If I'm not mistaken, this is the usual situation with Visual Studio. With g++, you have to invoke the compiler with -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC. (It's probable that you don't need all three, but I use all
three systematically.) With other compilers, check the documentation. The purpose of the undefined behavior in the standard here is precisely to allow this sort of thing.
In decreasing order of preference:
If you utilize iterators, ranges, and iteration rather than indexes into the container, the problem just goes away because you are no longer passing in arbitrary indexes that need to be checked. At that point you may decide to replace any remaining code that requires indexes with at instead of using a special container.
Extend with algorithms rather than inheritance as suggested in one of the comments. This will almost certainly be completely inlined away and is consistent with the standard using algorithms rather than additional member functions. It also has the advantage of working with any container that has operator[] and at (so it would also work on deque):
template <typename Container>
const typename Container::value_type& element_at(const Container& c, int index)
{
// Do checked code here.
}
Privately inherit std::vector and using the methods you need into your child class. Then at least you can't improperly polomorphically destroy your child vector.

Most efficient way to process all items in an unknown container?

I'm doing a computation in C++ and it has to be as fast as possible (it is executed 60 times per second with possibly large data). During the computation, a certain set of items have to be processed. However, in different cases, different implementations of the item storage are optimal, so i need to use an abstract class for that.
My question is, what is the most common and most efficient way to do an action with each of the items in C++? (I don't need to change the structure of the container during that.) I have thought of two possible solutions:
Make iterators for the storage classes. (They're also mine, so i can add it.) This is common in Java, but doesn't seem very 'C' to me:
class Iterator {
public:
bool more() const;
Item * next();
}
Add sort of an abstract handler, which would be overriden in the computation part and would include the code to be called on each item:
class Handler {
public:
virtual void process(Item &item) = 0;
}
(Only a function pointer wouldn't be enough because it has to also bring some other data.)
Something completely different?
The second option seems a bit better to me since the items could in fact be processed in a single loop without interruption, but it makes the code quite messy as i would have to make quite a lot of derived classes. What would you suggest?
Thanks.
Edit: To be more exact, the storage data type isn't exactly just an ADT, it has means of only finding only a specific subset of the elements in it based on some parameters, which i need to then process, so i can't prepare all of them in an array or something.
#include <algorithm>
Have a look at the existing containers provided by the C++ standard, and functions such as for_each.
For a comparison of C++ container iteration to interfaces in "modern" languages, see this answer of mine. The other answers have good examples of what the idiomatic C++ way looks like in practice.
Using templated functors, as the standard containers and algorithms do, will definitely give you a speed advantage over virtual dispatch (although sometimes the compiler can devirtualize calls, don't count on it).
C++ has iterators already. It's not a particularly "Java" thing. (Note that their interface is different, though, and they're much more efficient than their Java equivalents)
As for the second approach, calling a virtual function for every element is going to hurt performance if you're worried about throughput.
If you can (pre-)sort your data so that all objects of the same type are stored consecutively, then you can select the function to call once, and then apply it to all elements of that type. Otherwise, you'll have to go through the indirection/type check of a virtual function or another mechanism to perform the appropriate action for every individual element.
What gave you the impression that iterators are not very C++-like? The standard library is full of them (see this), and includes a wide range of algorithms that can be used to effectively perform tasks on a wide range of standard container types.
If you use the STL containers you can save re-inventing the wheel and get easy access to a wide variety of pre-defined algorithms. This is almost always better than writing your own equivalent container with an ad-hoc iteration solution.
A function template perhaps:
template <typename C>
void process(C & c)
{
typedef typename C::value_type type;
for (type & x : c) { do_something_with(x); }
}
The iteration will use the containers iterators, which is generally as efficient as you can get.
You can specialize the template for specific containers.

AnyIterator and boost iterator facade

Is it possible to implement an any iterator with boost iterator facade?
I don't want to define implementation details in my baseclass
class Base
{
public:
typedef std::vector<int>::iterator iterator;//implementation detail
...
virtual iterator begin()=0;
virtual iterator end()=0;
};
or do i have to write one completely from scratch;
The code you've posted has fixed the type of iterators returned from Base and all it's implementantions to std::vector<int>::iterator which is probably not what you want. Jeremiah's suggestion is one way to go with one drawback: you loose compatibility with STL... I know of three implementations of a polymorphic iterator wrapper:
becker's any_iterator (which implements boost::iterator_facade)
the opaque_iterator library (google for it), or
Adobe's very interesting poly library which contains a hierarchy of STL conforming any_iterators.
The problem is harder than it might seem... I made an attempt myself mainly because I needed covariance in any_iterators type argument (any_iterator<Derived> should be automatically convertible to any_iterator<Base>) which is difficult to implement cleanly with STL like iterators. A C# like Enumerator<T> is easier to implement(*) (and imho generally a cleaner concept than STL-like pairs of iterators) but again, you "loose" the STL.
(*) = without 'yield' of course :-)
I think this may be what you're looking for:
any_iterator: Type Erasure for C++ Iterators
Here's a snippet from that page::
Overview
The class template any_iterator is the analog to boost::function for
iterators. It allows you to have a single variable and assign to it
iterators of different types, as long as these iterators have a
suitable commonality.

Proper use of of typedef in C++

I have coworkers who occasionally use typedef to avoid typing. For example:
typedef std::list<Foobar> FoobarList;
...
FoobarList GetFoobars();
Personally, I always hate coming across code like this, largely because it forces me to go lookup the typedef so I can tell how to use it. I also feel like this sort of thing is a potential slippery slope... If you do this, why aren't you doing it more? (pretty soon, your code is totally obfuscated). I found this SO question regarding this issue:
when should I use typedef in C
I have two questions: 1) am I truly alone in disliking this? 2) If the vast majority of people think this sort of typedef use is OK, what criteria do you use to determine whether to typedef a type?
The two big arguments for this type of typedef are the reduced typing, which you've already mentioned, and the ease of changing over to a new type of container. A FoobarList could be backed by a vector or a list or a deque and switching would often just require changing a typedef.
Your dislike of them when it comes to looking them up, is quite reduced when dealing with IDEs, since I can just hover over the type name, and the IDE tells me what it's defined as.
The more useful situations are when you have nested containers - you can give the names some semantic meaning without having to define entire classes:
typedef std::list<Foobar> FoobarList;
typedef std::map <string, FoobarList> GizmosToFoobarsMap;
You can also save a LOT of typing when dealing with iterators of these types (although that's reduced now that C++0x has auto.)
typedefs are essential to STL and template programming in general. Just look at how iterator traits work:
template <class Iterator>
struct iterator_traits {
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
template <class T>
struct iterator_traits<T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
As for "shortcut" usage of typedefs - I think it's perfectly fine when localized in an implementation file. I have the same rule here as for using namespace - if it saves me typing and doesn't confuse others, go for it.
I like typedefs like that because they improve readability. Consider having std::vector<std::string>::const_iterator all over the place, or even std::map<std::string, std::vector<std::string> >::iterator. Half your code ends up just describing types, and a bunch of typedefs simplifies that a lot. I don't think it's too much of a hurdle to understanding either - IDEs can usually tell you the type if you hover the mouse over it or go-to-definition, and working with code usually requires you understand things like this anyway.
I like that typedef because it allows to change the type of the container later (say, profiling showed std::deque to be faster than std::list) without changing all the code in question.
And in case you wonder: I don't object to the thing being called a list, even though it might be a std::deque. In this context I see "list" as a conceptual term, not a data structure. (You don't do your shopping lists as doubly linked lists, do you?)
Personally I also typedef STL stuff, the list and the iterator (Foos and FooIterator). Used everywhere makes for a very clear (imo) style that you get used to by the 2nd occurance.
Besides you can just mouse over the type to see what it really means in any real IDE (vs or eclipse), so you have all the information you need right at its point of use in addition to not having to scroll 3 screens to the right just to read the full line.
With the C++0x auto keyword this won't be needed anymore. Yes, I'm a believer in C#'s var keyword, and again you can mouse over it to see the type if you're in doubt!
I don't do that in my code either, so I guess you are not alone. To my mind it makes one more thing that the reader has to go look up. The poor code reader generally has more than enough of those already.
In your example FoobarList is no different from any other class; you'd still have to look the definition or documentation to know how to use it; and you would not use that as an argument for not using classes!
In this case once you'd determined that it was an STL std::list, you'd know how to use it or at least where to find good quality documentation; which is probably more than you can say for most classes that may be defined in your project.
That said I am ambivalent as to whether it is a good idea or not; I just think that it is mostly harmless.
I personally find that typedefs are very useful when dealing with templated code, both when writing templates, and when instantiating them.
Writing templates:
typedefs are required for template metaprogramming. For Example, removing const:
template<typename T>
struct RemoveConst
{
typedef T Type;
};
template<>
struct RemoveConst<const T>
{
typedef T Type;
};
Now, we can access the const-less type from any T by instantiating RemoveConst::Type
Instantiating templates:
Like a lot of things in programming, right tool for the right job.
typedefs such as your example
typedef std::list<Foobar> FoobarList;
...
FoobarList GetFoobars();
Sound completely reasonable, mainly because the typedefed name is descriptive(a FoobarList is a List of Foobars). This is very useful particularly when dealing with STL containers, or any other template types that share the same interface. imagine the following class declaration:
class SomeClass
{
...
std::vector<int> mContainer;
};
This class is likely to iterate over the elements of Container, which would result in code similar to:
for(std::vector<int>::iterator It = mContainer.begin(); It != mContainer.end(); ++It)
{
}
Now imagine that you realize, after writing the above for-loop in 5 different metods, that you are constantly inserting in the middle of the array, and that a std::list would be much better suited for the job.
In this case, you would have to go through every instance of std::vector::iterator, and change the declaration.
Instead, What you can do, is typedef the container you are using inside the class:
class SomeClass
{
typedef std::vector<int> IntContainer;
...
IntContainer mContainer;
};
This can allow you to write highly generic code, that can be very easily modifiable.
for(IntContainer::iterator It = mContainer.begin(); It != mContainer.end(); ++It)
{
}
In this case, you only need to change the typedef of IntContainer, and any instance that refers to it, is automatically changed.
You see typedefs a lot when you need to write C++ code that works across platforms, because the size of the fundamental datatypes are not fixed. For example, the Java virtual machine has typedefs for the fundamental types for different compilers.
I think the typedef is good practice in this case. While the template syntax puts the parameters in you face, they are usually the sort of things one would try to encapsulate in an object oriented environment.
typedef'ing the template performs that encapsulation.
If I want the ending type to be strongly typed, I typically prefer inheritance over typedef, e.g.
class CMyMap : public CMap<int, int> {...}
This way, CMyMap is strongly typed - I just can't pass any CMap<int, int> into a method that takes a CMyMap as a parameter. typedef just tells the compiler "another name for", but class definition defines a new type.
If I defined a function
void foo(const CMyMap &map);
but I used typedef to define CMyMap, e.g.
typdef CMap<int, int> CMyMap;
then someone could do
CMap<int, int> myMap;
foo(myMap);
and the compiler would be quite happy.
But if I really want foo to be strongly typed and ONLY take CMyMap, then inheritance is my mechanism of choice for "typing".
BTW, CMyMap is kindof generic, but something more specific might be CPhoneNumber2Index where the phone number is represented as an integer and the index is an integer. It is obvious here that my CPhoneNumber2Index is not just a map from an integer to another integer. So foo might be
string ReverseLookup(const CPhoneNumber2Index &PhoneBook, int iPhoneNumber);
which shows that ReverseLookup has something to do with phone numbers, not CMap<int, int>
After some heavy messing with templates, typedef behaves like normal variable assignment...