Краткий ответ
Проблема в том, что ss << L"text"
дает вам std::wostream
, а не std::wstringstream
.
Вы только создали operator<<
для std::wstringstream
, поэтому следующая операция (которую вы пытаетесь выполнить на a
) не удалась.
Длинный ответ
Когда вы пишете что-то вроде
ss << L"text" << a << endl;
вы не вызываете функцию с четырьмя аргументами.
Фактически вы объединяете несколько операций:
((ss << L"text") << a) << endl;
Это работает, потому что каждая операция operator<<
возвращает ссылку на исходный объект потока, так что вы можете продолжить цепочку следующих операций таким образом.
Но поскольку iostreams формируют иерархию наследования и поскольку operator<<
применим к любому выходному потоку, тип возврата из вашей операции на wstringstream
является чем-то немного менее конкретным, чем wstringstream
.
Фактически, ss << L"text"
оценивается как wostream&
(wostream
является одним из базовых классов wstringstream
). Ссылка все еще ссылается на тот же оригинальный объект потока ... но у него есть тип базового класса.
Итак, ваша вторая операция с a
имеет следующие активные операнды:
- a
wostream&
(на LHS)
- a
Test
(по RHS)
Но у вас нет wostream& operator<<(wostream&, Test const&)
. Вы только создали wstringstream& operator<<(wstringstream& sstream, Test const& test)
, поэтому совпадений нет.
Таким образом, фактически, при создании operator<<
для широких iostreams, вы должны заставить его работать на все wostream
с (ясно, что нет никаких оснований ограничивать его wstringstreams
):
wostream& operator<<(wostream& sstream, Test const& test)
{
sstream << test.f;
return sstream;
}
Идем дальше, зачем ограничиваться широкими потоками? Почему не нормальные тоже?
template<typename CharT, typename TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& sstream, Test const& test)
{
sstream << test.f;
return sstream;
}
Теперь вы сможете правильно передавать потоки объектов вашего Test
класса в wostream
s, ostream
s и всех их потомков.