The second part of the question is the most interesting one to me. I prefer to put typedef
s within the classes that use them, when there's a logical place for them, even if they're used in other classes. But that causes some problems with forward declarations (which we use heavily for compile-speed).
For example, in one recent project we had a class called Io
, with an embedded typedef called Point
, which made for very readable code -- an Io::Point
is very clear and readable. But whenever we wanted to use the type, we had to include the declaration of the Io
class, even if all we needed was the declaration of Io::Point
, since there's no way (that I know of) to forward-declare a type that's within a forward-declared class.
In that case, we ended up doing it both ways. We created a global IoPoint
type, and then typedef
d Io::Point
to it (so that our already-written code didn't have to be modified). Not the prettiest answer, but it got the job done.
As for the other parts:
We don't use any special convention for the names. For maps, we often use DescriptiveSomethingMap (since it's unlikely that we'll ever change from a map to some other container type), but if DescriptiveSomething is descriptive enough and doesn't conflict with an existing name, we'll often use it instead.
We generally don't bother creating typedefs for the iterators, since it's easy (and very readable) to simply use Type::iterator
or Type::const_iterator
. That said, we do sometimes typedef them if the type name is so long that Type::const_iterator
makes the code look too "chunky." (Don't know of any better way to say it, but you probably know what I mean.)
We create different typedefs for each concept, even if two of them define exactly the same type. They can change independent of one another, so having different type names for them simplifies any later refactoring. It also makes for more readable code, in many cases.