运算符的过载<<使用basic_ostream

时间:2015-11-02 12:15:46

标签: c++ templates operator-overloading std stream-operators

为什么使用用户定义的类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来完成流操作符的重载,这是char std::basic_ostream的typedef,以及为什么不直接使用{{1}完成}

例如:

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<<charstd::ostream,...)的流对象。 因此,如果使用std::ostringstreamstd::ostream更具限制性, 在讨论流操作符重载时,为什么std::basic_ostream从未被提及?

1 个答案:

答案 0 :(得分:2)

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

  1. Windows使用wchar_t作为很久以前Unicode人员做出的承诺的结果(Unicode只使用16位,每个字符只包含一个单元),并且自那时起就被破坏了。
  2. 其他人都使用char,现在大多数人认为它是UTF-8编码中的一个字节(显然,不是普遍的)。
  3. 回想起来,wchar_t(尤其是char16_tchar32_t)的引入是不明智的,只有char才会让世界变得更好会被使用。因此,那些不受Windows困扰的人并不关心I / O操作的wchar_t版本,而Windows一般似乎都在IOStreams上运行(已知MSVC ++实现很慢,对此没有任何意图)。

    另一个原因是,编写模板化I / O运算符会增加已经复杂系统的复杂性。很少有人能够理解IOStreams,而在这些人中,更少有人对支持多种角色类型感兴趣。

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

    独立于如何定义模板化运算符,通常更多的工作。如果天真地完成(即,直接使用例如wchar_t),结果将是缓慢的,并且当正确地执行时(即,来自std::ctype<cT>的缓存结果),它将非常复杂。

    把它们放在一起:为什么要这么麻烦?

    如果我必须写信至std::ctype<cT>或从std::wostream读取,我实际创建了一个过滤流缓冲区,它只是使用合适的std::wistream来翻译写入/读取的字符facet(甚至只使用std::codecvt<...>&#39; s std::ctype<wchar_t>widen())。它不会处理字符串的正确国际化,但narrow()设施无论如何都不适合国际化(你需要ICU之类的东西)。< / p>