Если вы посмотрите, как объявлены все потоковые операторы, они имеют вид:
ostream& operator<<(ostream& out, const someType& val );
По сути, вы хотите, чтобы ваша перегруженная функция действительно выполняла операцию вывода, а затем возвращала новый обновленный оператор потока. Я хотел бы предложить следующее: обратите внимание, что это глобальная функция, а не член вашего класса:
ostream& operator<< (ostream& out, const MyCustomString& str )
{
return out << str.data;
}
Обратите внимание, что если ваш объект «data» был закрытым, что, как говорит базовый ООП, вероятно, должен, вы можете объявить вышеуказанный оператор внутри себя как функцию «friend». Это позволит ему получить доступ к закрытой переменной данных.