Подтвердить что ты не робот

Почему оператор << работает между std:: ostream и char функцией, не являющейся членом?

Когда я запустил следующую программу

#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), что объясняет вывод.

Я предполагаю, что функция operator<< между std::ostream и char объявлена ​​в другом месте:

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

В противном случае std::cout << a разрешит std::ostream::operator<<(int).

Мой вопрос: почему объявлено/определено как функция, не являющаяся членом? Существуют ли какие-либо известные проблемы, которые мешают ему быть функцией-членом?

4b9b3361

Ответ 1

В набор вставки для std::basic_ostream входят частичные специализации для вставки char, signed char, unsigned 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*);

и т.д.

Ответ 2

Одна из причин заключается в том, что общий совет С++ предпочитает использовать функции-члены, не являющиеся членами, для функций-членов. Это пункт 23 в Scott Meyer Effective С++. Это обсуждается в fooobar.com/info/148346/....