为什么 std::ostream 和 char 之间的 operator<< 函数是非成员函数?

Why is operator<< function between std::ostream and char a non-member function?

当我运行下面的程序

#include <iostream>

int main()
{
   char c = 'a';
   std::cout << c << std::endl;
   std::cout.operator<<(c) << std::endl;

   return 0;
}

我得到了输出

a
97

http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt 进一步挖掘,我注意到 std::ostream::operator<<() 没有以 char 作为参数类型的重载。函数调用 std::cout.operator<<(a) 解析为 std::ostream::operator<<(int),这解释了输出。

我假设 std::ostreamchar 之间的 operator<< 函数在别处声明为:

std::ostream& operator<<(std::ostream& out, char c);

否则,std::cout << a 将解析为 std::ostream::operator<<(int)

我的问题是为什么 declared/defined 是一个非成员函数?是否有任何已知问题阻止它成为成员函数?

std::basic_ostream 的插入器集包括用于将 charsigned charunsigned char 等插入 basic_ostream<char, ...> 流的部分特化。请注意,这些特化仅适用于 basic_ostream<char, ...> 流,不适用于 basic_ostream<wchar_t, ...> 流或基于任何其他字符类型的流。

如果将这些独立模板移动到主要 basic_ostream 定义中,它们将可用于 basic_ostream 的所有专业化形式。显然,图书馆作者想防止这种情况发生。

我真的不知道他们为什么要在更通用的基础上引入这些专业

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
                                        char);

插入者,但显然他们有他们的理由(优化?)。

C 字符串插入器也存在同样的情况。除了更通用的插入器

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
                                        const char*);

库规范也声明得更具体

template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,
                                       const char*);

等等。

一个原因是遵循一般的 C++ 建议,即优先使用 non-member non-friend 函数而不是成员函数。这是 Scott Meyer 的 Effective C++ 中的第 23 条。 Whosebug.

中对此进行了讨论