クラステンプレートのfriend宣言についての質問です。
あるクラステンプレートMyClass用のoperator<<をオーバーロードしたいとします。
敢えてfriend宣言のtemplateを省略し、

template <class T>
class MyClass {
...
friend std::ostream& operator<<(std::ostream&, const MyClass&);
};

template <class T>
std::ostream& operator<<(std::ostream& os, const MyClass<T>& m) { ... }

の形にすると「Undefined reference」となりコンパイルできませんが、

std::ostream& operator<<(std::ostream&, const MyClass<int>&) { ... }

のように明示的な関数を定義しておけば正常にコンパイルされ、実行できます。
(non-template-friend警告は無視しています)
なぜこのような差が生じてしまうのでしょうか?

MyClass<int>のインスタンスを作った際に、MyClass<int>が実体化され、
friend std::ostream& operator<<(std::ostream&, const MyClass<int>&);
の宣言が行われるかと思っていたのですが、もし宣言が行われているならば
最初の定義でマッチしないのは不自然に思えてしまいます。
実体化のタイミングがズレているのでしょうか?

長文失礼致しました。