ccache has been huge for me -- can't recommend it enough. The next big win for me was externing common templates into its own translation unit: http://gameangst.com/?p=246
I read the article, but I'm still a little confused. Do you put common std templates into their own translation unit, or are you putting only your own user-defined templates into their own translation unit?
Both, although most of the heavy ones in my projects are from the application-layer/user-defined.
having strings with common vector/map/unordered_map/set/unordered_set template specializations help a bit (i.e basic_string<char>, uint64_t int64_t, int and uint)
My methodology wasn't very scientific: when I found a template being specialized at a low-level, I added it to my list. another heuristic is anything that templates off of std::string (basic_string<char>), char, uint64_t int64_t, int and uint are all pretty good candidates as the likelyhood of them being reused everywhere is high.