#c
#c
Вопрос:
Рассмотрим этот пример:
#include <sstream>
#include <ctime>
using MyStream = std::stringstream;
struct MyTime
{
explicit MyTime(std::time_t time) // w/o explicit the MyTime operator << is ambigous as well
{
}
};
/*
having this overload of course solves everything, but that seems wrong
std::stringstream amp;operator<<(std::stringstream amp;stream, char c)
{
stream.put(c);
return stream;
}
*/
MyStreamamp; operator<<(MyStream amp;stream, std::time_t time)
{
return stream;
}
MyStreamamp; operator<<(MyStream amp;stream, const MyTime amp;time)
{
return stream;
}
int main(int argc, char **argv)
{
MyStream stream;
stream << 'Z';
return 0;
}
Без std::stringstream amp;operator<<(std::stringstream amp;stream, char c)
объявления stream << 'Z'
сбой завершается с неопределенностью (поскольку для него нет перегрузки char
, его можно повысить как до short , так и до hit basic_ostream
, а также до time_t
и hit MyStream
). Я действительно не хочу использовать basic_ostream::put
), поскольку цепочка из нескольких записей будет выглядеть уродливо (конечно, если это последнее средство, тогда …). Итак, это вызывает у меня два вопроса:
- В чем причина отсутствия
char
перегрузкиbasic_ostream::operator<<
? Это все сводится к кодировкам символов? - Есть ли какие-либо хорошие решения (что-то, чего мне не хватает, кроме использования
put
илиchar
перегрузки)?
Обновить
Таким образом, кажется, что наследование от std::stringstream
vs using using
устраняет проблему, но это ставит меня перед дилеммой идти против догмы «никогда не наследовать от классов stl».
Я предполагаю, что проблема возникает из-за того, что using
на самом деле не вводит новый тип, поэтому двусмысленность:
Объявление псевдонима типа вводит имя, которое может использоваться как синоним типа, обозначаемого type-id . Он не вводит новый тип и не может изменить значение существующего имени типа.
Комментарии:
1. Есть выбор между вашим
operator<<(std::stringstreamamp; stream, std::time_t time)
иtemplate <..>operator<<(basic_ostream<CharT,Traits>amp;, CharT)
. Ни один не лучше.2. Существует реализация для
char
, но это свободная функция , а не член. Я предполагаю, что он не выбирается, потому что он реализован наbasic_ostream
, а не на более конкретномstringstream
— что-то, что вы могли бы сделать и для своего пользовательского типа.3.Вы можете устранить проблему, внедрив перегрузку
std::ostream
вместоstd::stringstream
Demo .4. @Thomas ах, спасибо, я пропустил бесплатную функцию. Хорошо, это дает больше понимания.
5. @Jarod42 Я подумал об этом, я вроде как хотел, чтобы после этого было легко извлекать строку, но да, я могу просто обернуть свой собственный буфер и жить с
std::ostream
ним.
Ответ №1:
Вы можете устранить проблему, реализовав перегрузку с std::ostream
помощью вместо std::stringstream
std::ostreamamp; operator<<(std::ostream amp;stream, std::time_t )
{
return stream;
}
std::ostreamamp; operator<<(std::ostream amp;stream, const MyTime amp;)
{
return stream;
}
Комментарии:
1. Это решает проблему, хотя это лишает меня намерения иметь определенное поведение для моего точного типа потока, но я думаю, что нет лучших способов обойти это.
2. только что пришел к выводу, что на самом деле вывод (о чем все предупреждают для классов std) устраняет проблему. Извините, мне придется отказаться от этого, поскольку это сохраняет семантику, которая мне нужна. Но я не уверен, как на это влияют правила разрешения.