Здесь:
template <class T> istream& operator>>(istream& stream_in, rat<T> &rvalue) {
cout << "Enter rational value (a/b): ";
stream_in >> rvalue.ch;
stream_in.ignore();
stream_in >> rvalue.zn;
cout << endl;
return stream_in;
};
Не должно быть привязки к cout. Работа только с потоком stream_in, т.к. данные не обзательно считываются с консоли, а такой оператор должен предполагать и считывание из файла. Приглашение ко вводу нужно делать "в main", или реализовать метод для ввода с приглашением, принимающий два потока. Перевод строки также после ввода не нужно делать.
Основная проблема:
Не совсем правильное решение, см. комментарии:
public:
template <class T1>
friend istream& operator>>(istream& stream_in, rat<T1> &rvalue);
template <class T1>
friend ostream& operator<<(ostream& stream_out, const rat<T1> &rvalue);
UPD:
Правильное
template <class T> class rat;
template <class T> istream& operator>>(istream& stream_in, rat<T> &rvalue);
template <class T> ostream& operator<<(ostream& stream_out,const rat<T> &rvalue);
template <class T>
class rat{
T ch, zn;
public:
friend istream& operator>> <T> (istream& stream_in, rat &rvalue);
friend ostream& operator<< <T> (ostream& stream_out, const rat &rvalue);
//......
};