操作员过载<<带basic_ostream

Overload of operator<< with basic_ostream

本文关键字:lt ostream basic 操作员      更新时间:2023-10-16

为什么使用用户定义的类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完成的,这是一个用于std::basic_ostream char的typedef,为什么不直接用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::ostreamstd::ostringstream、...(。因此,如果使用std::ostreamstd::basic_ostream更具限制性,为什么在谈论流运算符重载时从未提及std::basic_ostream

实际上,使用两种不同的字符类型:

  1. Windows使用wchar_t是Unicode人很久以前做出的承诺的结果(Unicode将只使用16位,每个字符将仅包含一个单元(,并且此后一直被打破。
  2. 其他人都使用char现在主要被认为是 UTF-8 编码中的一个字节(显然,不是通用的(。

回想起来,引入wchar_t(甚至更何况char16_tchar32_t(是不明智的,如果只使用char,世界会变得更好。因此,那些不受Windows困扰的人并不关心wchar_t版本的I/O操作,而Windows通常似乎在IOStreams上打赌(众所周知,MSVC++实现很慢,并且没有打算对此做任何事情(。

另一个原因是,编写模板化的 I/O 运算符被认为增加了已经复杂的系统的复杂性。似乎很少有人了解 IOStreams,在这少数人中,对支持多种字符类型感兴趣的人更少。

模板化 I/O 运算符感知复杂性的一个方面是假设实现需要进入标头,当然,这是不正确的,因为基本上只有两种字符类型是 IOStreams 实例化(charwchar_t (: 尽管 IOStreams 可以用其他字符类型实例化, 我很确定几乎没有人真正这样做。虽然我知道这需要什么,但我可能仍然需要至少一天的时间来定义所有必要的方面。因此,模板定义可以在合适的翻译单元中定义并在那里实例化。或者,不是定义运算符是模板,而是可以完全专业化。

独立于如何定义模板化运算符,通常工作量更大。如果天真地完成(即直接使用例如std::ctype<cT>(,结果会很慢,当做得正确时(即,从std::ctype<cT>缓存结果(,它将非常复杂。

综合起来:何必呢?

如果我必须写入std::wostream或从std::wistream读取,我实际上会创建一个过滤流缓冲区,它只是使用合适的std::codecvt<...>方面(甚至只是使用std::ctype<wchar_t>widen()narrow()(来转换写入/读取的字符。它不会处理字符串的正确国际化,但无论如何,std::locale设施都无法真正达到适当的国际化(为此您需要像 ICU 这样的东西(。