2009-11-09
C++ Pitfalls
As I do no C++ hacking at ETH I have not stumbled upon new input for this blog on my own. So I am very happy that Roker keeps on feeding me.
Today he pointed me at Cay Horstmann's list of C++ pitfalls. Some of the issues have already been covered here but some haven't. I recommend reading it to every C++ developer as this takes less time than learning it the hard way by debugging code. Have fun.
Concerning the iterator issues Cay provides a Safe STL implementation which is supposed to be used as a drop in replacement for the STL during development. It adds state and knowledge about the owner to iterators and uses this information to do runtime checks. If you accidently use your iterators in a wrong way you end up with a comprehensive runtime error instead of a segfault "deep in the bowels of STL code".
I haven't tested Safe STL. If anybody did feel free to send me your experience. I would be glad to blog about it.
2009-11-09
Catching Integer Overflows in C
abs may return a negative number. Comforting to know that C++ inherited this behaviour....
2009-08-22
The Safe Bool Idiom
Operator overloading is considered a major C++ feature. But as so often with C++ this feature sometimes clashes with other language properties.
Roker pointed me to an article about
the safe bool idiom
where the author elaborates on why a simple operator bool is not
satisfying if you want to be able to use an object within a bool context. Have
fun...
2009-07-09
feature collision
One thing the C++ community is pretty proud of is that, in contrast to C, C++ supports const correctness. Turns out that const correctness clashes with STL containers.
Today Roker pointed me to a poor guy from #c++@freenode with the following problem:
#include <iostream>
#include <list>
typedef std::list<int> list_t;
list_t::const_iterator find_first_odd(const list_t & list)
{
for (list_t::const_iterator i = list.begin(); i != list.end(); ++i)
{
if (*i % 2 != 0) return i;
}
return list.end();
}
int main()
{
list_t list;
list.push_back(2);
list.push_back(3);
list.push_back(4);
list_t::const_iterator odd_i = find_first_odd(list);
if (odd_i != list.end())
// Error. Can not use const_iterator with 'std::list::erase'
list.erase(odd_i);
return 0;
}
For the sake of const correctness the function find_first_odd
expects a constant reference to the list because it is not going to modify it.
But as a result the function can only return a const_iterator,
because there is no way to get a non-const iterator from the
constant list.
So the caller of find_first_odd ends up with a
const_iterator which is useless for modifying operations such as
erase. And for him it is also impossible to turn the
const_iterator into a non-const iterator. The two
types have no relation to each other, so casting does not work. And there are
no conversion functions in the STL either. So the only way out here is to
sacrifice const correctness and pass a non-const reference to
find_first_odd.
According to Roker nobody on #c++ had a better solution. And according to Scott Meyers' article Three Guidelines for Effective Iterator
Usage there is none. const_iterators can not be easily transformed
into iterators. What you can do is nasty and rather inefficient.
Here it comes:
template <class Container>
typename Container::iterator convert(typename Container::const_iterator in, Container& container)
{
typename Container::iterator out(container.begin());
std::advance(out, std::distance<typename Container::const_iterator>(out, in));
return out;
}
If the container does not support random access, this conversion is O(n).
Furthermore it can only be done, if the container object is at hand. Finally
note, that this function violates const correctness, because the container object
which is not altered by the function is not passed as const&.
The reason is that the begin() function of a constant container
returns a const_iterator which you can not convert into the output
non-const iterator. In case you are confused, try this illustration.
2009-06-22
C++ truths
Since I am at the ETH in Zurich I haven't used C++. The reason is simply the fact that I haven't encountered any problem for which C++ is the tool of choice. That's why there has been almost no input to this category from me.
But there are others who blog about C++. So I will be satisfied with passively following the C++ topic and refering to them.
Today's featured C++ blog is C++ thruths from Sumant Tambe. Hmm, infinite regress, yummy. ;-)
Thank you Roker
2009-05-20
the longest suicide note in history
I am not alone with my estimation of C++ being a dead end. Today Roker pointed me to an article from Allan Kelly about the future of C++. Here is my favourite quote:
[the C++ 0x standard will be] the longest suicide note in history.
Other languages do better. Python 3.0 and Perl 6 are not downward compatible and in both cases I think this is a good idea. Why is this impossible for C++?
2009-03-30
git
Rico und ich haben beim Chaostreff Rheintal und dem net culture lab Dornbirn einen Vortrag über das Versionsverwaltungssystem git gehalten.
Links zu den Folien und den Aufzeichnungen gibt es hier.
2009-02-20
moving on
I am a PhD student at ETH Zurich now. Besides other cool infrastructure the ETH provides blogs for associates. No doubt, I had to try out.
It's a WordPress, so I am leaving the nanoblogger paradigm of static page content. What I can get is interaction through reader comments and trackbacks. But I'm also a target for spam and crackers now. We'll see...
Anyway, here is copton's ETH blog. For the time being new posts will go there.
2009-02-15
C Traps
Quite a time ago Andrew König has written a book about C traps and pitfalls. Today, Roker pointed me on an earlier technical report which was the basis of the book.
Although some things are different with C++, I recommend everybody to read at least the report. Otherwise you surely will stumble on those items sooner or later.
2009-01-25
static initialization fiasco
Recently I got an email with the following question to the C++ and the linker article:
In the example in the "Dynamic initialisation" section, the constructors for A and B use std::cout. Is std::cout guaranteed to be available at that point?
The A and B objects in the cited example are static objects. So are
std::cout, std:cerr and std::cin. The problem is that the
order of initialization of static objects is undefined. In case there are no extra rules for the
input/output objects, the constructors of A and B indeed might use them
uninitialized.
In fact, there are no special rules for the input/output objects. Instead the standard simply says in section 27.3
The objects [cout, cin, cerr] are constructed [...] before the body of main begins execution.264) The objects are not destroyed during program execution.265)with the footnotes saying
264) If it is possible for them to do so, implementations are encouraged to initialize the objects earlier than required.
265) Constructors and destructors for static objects can access these objects to read input from stdin or write output to stdout or stderr.
Footnote 264 is vary vague. I interprete it like this: Strictly spoken it is not guaranteed, that
std::cout exists during the execution of constructors of static objects. But the
implementation is not forbidden to give this guarantee on its own. And I would guess that all
practically important implementations do so.
Footnote 265 is a bit confusing. Sure, you "can" use it, but there is no guarantee that it works, as implementations are only encouraged but not forced to initialize the input/output objects betimes.
So, my answer to the question is: as far as I can see, using cout et al in constructors
of static objects is theoretically not portable. But in practise it should be a safe bet.
Platform independence is overestimated anyway!
Thanks to Michael

