The Joy of C++

So I just finished messing with this library I got online to do tensor voting stuff.  The website where I got the source code was last updated in 2002, as was the code itself.  After two days of fighting with C++, I've come to the conclusion that successfully compiling and linking a moderately sized library which makes heavy use of templates is akin to constructing a large building out of toothpicks and Elmer's glue.  I eventually got the code to compile and link, but spent about four hours struggling with one particularly annoying problem.  Apparently, if a templated class contains a friend function, that function must be defined where it is declared if the linker is to find the definition during linking.  How screwy is that?  Now, templates normally mess with my fairly standard ".hpp/.cpp" paradigm; where I define the interface of a class in a header file and the implementation of the class in a ".cpp" file.  Because of the nature of the beast (templates) and various compilers' different levels of support for language features such as the export keyword, I usually end up #including the ".cpp" source files for templated classes in the ".hpp" headers where they are declared.  It's ugly, but fine.  I mean, that's the way the STL does it, and it works fine for them.  However, this particular issue is even more nefarious.  For the friend function of a template class, the definition must be exactly where the declaration is.  That means I can't declare the friend function and the define it later in the same file outside of the class, but I must put the entire definition in the class delcaration.  Let me give an example; instead of

template <typename T>
class MyTemplateClass{
     ...
     friend ostream& operator<< ( ostream& os, const MyTemplateClass& mtc );
};
 
ostream& operator<< ( ostream& os, const MyTemplateClass<T>& mtc ){
	os << mtc.member_var_1 << .... ;
}

One must do

template <typename T>
class MyTemplateClass{
     ...
     friend ostream& operator<< ( ostream& os, const MyTemplateClass& mtc ){
         os << mtc.member_var_1 << .... ;
     }
};

This particular quirk of the language is frustrating, and stupid. I'd really like an explanation of why
it's necessary... Anyone? Anyway, that's my piece about C++, templates, and old code.