It’s a large topic, but the most important goal is to minimize the amount of code that’s transitively included in headers.
That can mean avoiding templates, or (if you’re willing to do the work) using explicit instantiations in one source file only.
Use the PImpl pattern so that users of a class don’t need to know the declarations of its private members.
And whenever reasonable, design your method signatures so that objects are passed by pointer/reference — this means you can work with forward declarations instead of always having to include the full class declaration.
Do all of that only where reasonable. Small headers usually don’t matter much, and avoiding dependencies on headers that users are likely to include anyway (like <string>) doesn’t win anything either.
That can mean avoiding templates, or (if you’re willing to do the work) using explicit instantiations in one source file only.
Use the PImpl pattern so that users of a class don’t need to know the declarations of its private members.
And whenever reasonable, design your method signatures so that objects are passed by pointer/reference — this means you can work with forward declarations instead of always having to include the full class declaration.
Do all of that only where reasonable. Small headers usually don’t matter much, and avoiding dependencies on headers that users are likely to include anyway (like <string>) doesn’t win anything either.