3

为什么带有用户定义类的流操作的典型标头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);

我的问题是为什么流运算符的通常重载是用 来完成的,它是ofstd::ostream的 typedef ,为什么不直接用 来完成?charstd::basic_ostreamstd::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, ...) 的流对象。因此,如果 usingstd::ostream比 更受限制std::basic_ostream,为什么std::basic_ostream在谈论流运算符重载时从未提及?

4

1 回答 1

2

在实践中,使用了两种不同的字符类型:

  1. Windows 使用wchar_t是由于 Unicode 人很久以前做出的承诺(Unicode 将只使用 16 位,并且每个字符仅包含一个单元),并且从那以后就被打破了。
  2. 其他所有人都使用char它现在主要被认为是 UTF-8 编码中的一个字节(显然,不是普遍的)。

回想起来,引入wchar_t(甚至更多地引入char16_tand char32_t)是不明智的,如果只char使用它,世界会变得更好。结果,那些不受 Windows 困扰的人并不关心wchar_tI/O 操作的版本,而且 Windows 通常似乎在 IOStreams 上大打出手(众所周知,MSVC++ 实现很慢,做任何事情的意图为零关于它)。

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

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

独立于如何定义模板化操作符,通常需要更多的工作。如果天真地完成(即,直接使用 eg, std::ctype<cT>)结果会很慢,如果做得正确(即从 缓存结果std::ctype<cT>),它会非常复杂。

综上所述:何必呢?

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

于 2015-11-02T13:31:03.463 回答