Monday, July 16, 2012

Four interesting questions - Part II

In a previous post I told, I am going to writing a series of articles on some interesting IT related questions and has already written one. This is the second one of that series. Its a C++ programming question. I found this question on a C/C++ answer script that was given for me to mark (From what I can remember no one had come up with a right answer).

The question was to write a C++ function that accepts any STL container and print all the members in it.

The point here is Standard Template Library containers are not derived from a common super class like in Java Collections. If it was the case we could simply write a function accepting that type. (In the case of Java most Generic containers with the exception of maps are derived from the Iterable interface). In Java we can write something similar to this one. (This will not handle maps but we are very close to it :))

public static
<T> void print(Iterable<T> iterable) {
for(T t : iterable) {
System.out.println(t);
}
}

How can we do this in C++ for the STL containers. The key for the answer is C++ Templates introduces a different paradigm of programming (based on static polymorphism). We can write a templated function.
But how?. We need to know a bit more about iterators. Iterators are the common way of accessing the elements in a STL container. Every STL container exposes its own iterator type through the public typedef, const_iterator and iterator. Although the actual iterators are of different types (read about how STL iterators are classified based on their contract) they have basic behaviors (overloaded operators that will do it). Based on these capabilties we can categorize iterators into a hierarchy. If we only use the operators of a fundamental iterator (i.e. forward Iterator
we can accomplish the former task).

The rest is about expressing that in valid C++ syntax. Here the typename key word is used to represent the partial type which is validated when the function is instantiated again for the actual container type. Note the typename keyword should be used before T otherwise it is interpreted as a static member const_iterator of class T.

template
<typename T> void print(T & con) {
typename T::const_iterator it = con.begin();
while(it != con.end()) {
std::cout << *it << std::endl;
++it;
}
}

Even a map can be passed as an argument provided that << operator is implemented for std::pair. The answer for the question is of few lines but it opens the way to a world of new possibilities. C++ templates are not only about writing containers of general types. Its much much more.

No comments:

Post a Comment