Thé*_*lst 4 c++ templates operator-overloading std stream-operators
为什么使用用户定义的类进行流操作的典型标头C通常如下所示:
std::ostream& operator<<(std::ostream& os, const C& c);
std::istream& operator>>(std::istream& is, C&);
Run Code Online (Sandbox Code Playgroud)
而不是这样的:
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);
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么流运算符的通常重载是用 完成的,它是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
}
Run Code Online (Sandbox Code Playgroud)
这里写operator<<的限制我们只能使用专门用于char(std::ostream,,std::ostringstream...)的流对象。因此,如果 usingstd::ostream比 更有限制std::basic_ostream,为什么std::basic_ostream在谈论流运算符重载时从未提及?
在实践中,使用两种不同的字符类型:
wchar_tUnicode 是人们很久以前做出的承诺(Unicode 将仅使用 16 位,并且每个字符仅由一个单元组成),但此后这些承诺已被打破。char它,现在大多数被认为是 UTF-8 编码中的一个字节(显然,不普遍)。回想起来,引入wchar_t(尤其是char16_t和char32_t)是不明智的,如果char使用的话世界会变得更好。因此,那些不被 Windows 困扰的人并不关心wchar_tI/O 操作的版本,并且 Windows 一般来说似乎在 IOStream 上押注(已知 MSVC++ 实现速度很慢,并且做任何事情的意图为零)关于它)。
另一个原因是编写模板化 I/O 运算符被认为会增加本已复杂的系统的复杂性。似乎很少有人了解 IOStreams,其中对支持多种字符类型感兴趣的人就更少了。
模板化 I/O 运算符的复杂性的一个方面是假设实现需要进入标头,这当然是不正确的,因为本质上只有两种字符类型 IOStream 是用 (char和wchar_t) 实例化的: IOStreams可以用其他字符类型实例化,我很确定几乎没有人真正这样做。尽管我知道需要什么,但我可能仍然需要至少一天的时间来定义所有必要的方面。因此,模板定义可以在合适的翻译单元中定义并在那里实例化。或者,不是将运算符定义为模板,而是可以完全专门化。
与模板化运算符的定义方式无关,它通常需要更多工作。如果天真地完成(即,直接使用例如,std::ctype<cT>),结果将会很慢,而当正确执行时(即,缓存来自 的结果std::ctype<cT>),它将非常复杂。
综合考虑:为什么要麻烦呢?
如果我必须写入std::wostream或读取,我实际上会创建一个过滤流缓冲区,它只是使用合适的方面(或者甚至只是使用's或)std::wistream来转换写入/读取的字符。它不会处理字符串的适当国际化,但无论如何,这些设施并不能真正达到适当的国际化(你需要像ICU这样的东西)。std::codecvt<...>std::ctype<wchar_t>widen()narrow()std::locale