【问题标题】:Why do overloads of 'operator<<' exist for the 'char' partial-specializations of std::basic_ostream?为什么 std::basic_ostream 的 'char' 部分特化存在 'operator<<' 的重载?
【发布时间】:2013-02-04 09:25:50
【问题描述】:

我想知道为什么basic_ostreamchar 部分专业化存在以下operator&lt;&lt; 重载:

template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
                                        char ch );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
                                        signed char ch );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
                                        unsigned char ch );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,  
                                        const char* s );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
                                        const signed char* s );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,traits>& os,
                                        const unsigned char* s );

为什么我想知道

我发现重载充其量是多余的,而且通常很麻烦:

  1. 已经存在以下非专用模板类型的重载,并提供charchar* 功能:

    template< class CharT, class Traits>
    basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                             CharT ch );
    template< class CharT, class Traits>
    basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                             char ch );
    template< class CharT, class Traits >
    basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                             const CharT* s );
    template< class CharT, class Traits >
    basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                             const char* s );
    
  2. signed charunsigned char 不是字符类型,(它们没有 char_traits),它们应该可以用作整数值,(尤其是在 int8_tstdint.h 上下文中, uint8_t 等)然而这些重载与这两点形成对比;人们必须玩游戏来解决这些烦恼,例如:

    • 针对每个用例将signed char 显式转换为signed shortunsigned char 转换为unsigned shortsigned char*unsigned char* 转换为void*
      • 这需要在用户代码中解决函数重载或模板部分特化。
    • 使用wchar_t 等效的basic_ostream 来避免这些不需要的函数重载。
      • 这可能会降低用户代码的性能。

    在这两种情况下,用户代码看起来都比实际需要的更丑。

【问题讨论】:

  • @LokiAstari 它与其中一个具有相同的表示,但它是一种不同的类型。
  • 关于 IOStreams 什么很麻烦?
  • 我认为您真正的问题不是存在重载,而是它们的行为就像您传递字符数据而不是整数一样。不是这个问题吗?
  • @BenjaminLindley,是的,这就是行为问题。 :-) 如果这些特定的重载不存在,我相信basic_ostream 的行为会更接近我的预期,并将signed charunsigned char 视为整数类型。但在创建库时一定有一些原因要添加特定的重载函数。

标签: c++ integer char operator-overloading ostream


【解决方案1】:

char 特征和各种 char 重载无关。

char 特征与 输出流 的 char 类型和处理有关,而 char 重载与 char 类型 inserted 有关。例如,想想basic_ostream&lt;wchar_t&gt;operator&lt;&lt;(basic_ostream, char)

您还必须考虑它是实现定义的,无论普通字符是signed 还是unsigned。还有

3.9.1 基本类型 [basic.fundamental]
1 ...普通字符、有符号字符和无符号字符是三种不同的类型。

因此,仅charconst char* 的重载并不能涵盖所有可能性。我想,定义这些重载只是为了完整并涵盖所有基本类型。

【讨论】:

  • 我知道basic_ostream 的第二个模板类型是用于格式化basic_ostream 本身,而不是operator&lt;&lt; 输入参数。 charsigned charunsigned char 是三种不同的 C 和 C++ 类型; (是的,char 的表示与signed charunsigned char 相同,但这与我的观点无关。)关键是charwchar_t 是唯一的字符类型,(在C++03 标准:) char_traitsbasic_stringbasic_ios 仅对这些类型有意义; c-string 文字只能为 charwchar_t 类型创建。
  • 我的意思是 signed charunsigned char 类型应该被视为任何其他整数(和非字符)类型。目前,signed char integer = 33; std::cout &lt;&lt; integer 将打印出!,而不是预期的33
【解决方案2】:

重载是允许在不指定所有模板类型的情况下使用运算符所必需的。如果类型匹配,编译器只使用正确的重载。如果它们不匹配,它要么必须进行隐式转换(不受欢迎),要么您必须明确指定所有模板类型,我什至不确定是否有语法可以让您这样做。

【讨论】:

  • 在我的解决方法示例中,我们已经必须将单个值显式转换为signed shortunsigned short,并指向void*;这些参数类型作为成员函数重载显式提供。我想替代方案必须包括signed charunsigned char 的成员函数重载,对于所有basic_streams。
猜你喜欢
  • 1970-01-01
  • 2016-12-01
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
相关资源
最近更新 更多