Перегрузка оператора & lt; & lt; с basic_ostream

Почему типичный заголовок потока управления с пользовательским классом C как правило, так:

std::ostream& operator<<(std::ostream& os, const C& c);
std::istream& operator>>(std::istream& is, C&);

и не так

template <class CharT, class Traits>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os
const C& c);

template <class CharT, class Traits>
std::basic_istream<CharT, Traits>& operator>>(
std::basic_istream<CharT, Traits>& is
C& c);

У меня вопрос, почему обычная перегрузка потоковых операторов выполняется с std::ostream, который является typedef для char из std::basic_ostreamи почему это не сделано напрямую с std::basic_ostream ?

Например:

class C
{
...
};

std::ostream& operator<<(std::ostream& os, const C& c)
{
...
}

int main()
{
C c;
std::wofstream myFile("myFile.txt");
myFile << c; //Impossible
}

operator<< здесь написано ограничить нас использовать только потоковый объект, который специализирован для char (std::ostream, std::ostringstream…)
Так что если использовать std::ostream более ограничивающий, чем std::basic_ostream,
Зачем std::basic_ostream никогда не упоминается при разговоре о перегрузке потоковых операторов?

1

Решение

На практике используются два разных типа символов:

  1. Windows использует wchar_t в результате обещаний, сделанных людьми Unicode давным-давно (этот Unicode будет использовать только 16 битов, и что каждый символ будет состоять только из одной единицы), и которые были нарушены с тех пор.
  2. Все остальные используют char который теперь в основном считается байтом в кодировке UTF-8 (очевидно, не универсально).

Оглядываясь назад, введение wchar_t (и тем более char16_t а также char32_t) был опрометчив, и мир был бы лучше, если бы char будет использоваться. В результате, те, кого не беспокоит Windows, не заботятся о wchar_t версия операций ввода-вывода и Windows в целом, похоже, используют IOStreams в целом (реализация MSVC ++, как известно, медленная и нет никаких намерений что-либо с этим делать).

Другая причина заключается в том, что написание шаблонных операторов ввода-вывода усложняет и без того сложную систему. Мало кто, кажется, понимает IOStreams, и среди этих немногих еще меньше людей заинтересованы в поддержке нескольких типов символов.

Одним из аспектов воспринимаемой сложности с шаблонными операторами ввода-вывода является предположение о том, что реализация должна идти в заголовок, что, конечно, неверно, учитывая, что в сущности есть только два символьных типа, для которых создаются IOStreams (char а также wchar_t): хотя IOStreams Можно быть реализованным с другими типами символов, я уверен, что вряд ли кто-то на самом деле делает это. Хотя я знаю, что для этого нужно, мне, вероятно, понадобится хотя бы день, чтобы определить все необходимые аспекты. Таким образом, определения шаблона мог быть определены в подходящих единицах перевода и созданы там. В качестве альтернативы, вместо определения операторов являются шаблонами, они могут быть полностью специализированными.

Независимо от того, как определены шаблонные операторы, обычно это больше работы. Если сделано наивно (то есть непосредственно с помощью, например, std::ctype<cT>) результат будет медленным и при правильном выполнении (т. е. кэширование результатов из std::ctype<cT>) это будет довольно сложно.

Взять все вместе: зачем?

Если бы мне пришлось написать std::wostream или читать из std::wistream Я бы на самом деле создал буфер потока фильтрации, который просто переводил бы написанные / прочитанные символы, используя подходящий std::codecvt<...> аспект (или даже просто используя std::ctype<wchar_t>«s widen() или же narrow()). Это не будет иметь дело с надлежащей интернационализацией строк, но std::locale в любом случае объекты не совсем соответствуют надлежащей интернационализации (вам нужно что-то вроде ICU для этого).

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]