#c #iostream #manipulators
Вопрос:
Я пытаюсь реализовать параметризованный манипулятор потоком для определенного набора данных. Я делаю это простым способом, как рекомендовано:
class print_my_data
{
private:
. . .
public:
print_my_data(. . .) { . . . }
ostreamamp; operator()(std::ostreamamp; out)
{
return out << . . . << endl;
}
};
ostreamamp; operator<<(ostreamamp; out, print_my_data md) // <=== MY QUESTION BELOW IS ABOUT THIS
{
return md(out);
}
Использование:
clog << print_my_data(. . .) << endl;
Это прекрасно работает; но я действительно не понимаю, почему это не работает, если я не определю operator<<
! Почему он не вызовет ту же перегруженную функцию, что и для endl
?? (т. Е. в качестве объекта, который может быть применен к потоку через operator()
)
Ответ №1:
Перегрузка, которую вы ищете, определена только для указателей функций.
basic_ostreamamp; operator<<( std::basic_ostream<CharT,Traits>amp; (*func)(std::basic_ostream<CharT,Traits>amp;) );
Ваш print_my_data
класс является вызываемым объектом (функтором, в терминах C ). Но это не указатель на функцию. С другой стороны, endl
является функцией и, следовательно, имеет указатель на функцию (на самом деле, это одна из немногих функций в стандартной библиотеке C , у которой есть адрес)
Можно было бы привести неразумный аргумент в пользу того, что перегрузка должна выглядеть так
basic_ostreamamp; operator<<( std::function<std::basic_ostream<CharT,Traits>amp;(std::basic_ostream<CharT,Traits>amp;)> func);
Но, увы, его не было рядом, когда были написаны операторы ввода-вывода. std::function
Как и понятия, если уж на то пошло. И используя SFINAE для объявления
template <typename F> basic_ostreamamp; operator<<( F func);
это просто открыло бы целый ящик Пандоры, полный грязных деталей, с которыми комитет по стандартам не хотел иметь дело.
Комментарии:
1. В любом случае, ни указатель на функцию
print_my_data
, ни a не являютсяstd::function
, и поэтому перегрузка также не будет выбрана.