Please don't mind me asking, but why do you compile your entire codebase often? What's the challenge of splitting it into units and compiling each of them independently when code is changed?
It's a cool little trick few people seem to know.
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.