It is illegal to use forward declarations with typedef names, as in:
class string; void f(string& s); //illegal, string is a typedef name
Even a typename won’t do here:
typename std::string; //still illegal void f(std::string& s);
The problem with these forward declarations is that std::string is not a class, but a typedef name defined like this:
typedef basic_string, allocator >string;
In order to generate the correct mangled name for the function f, the compiler has to see the non-typedef’d form of its argument. In other words, there is no escape from #including the header