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<char, char_traits<char>, allocator<char> >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 <string> in this case.