Если ваши манипуляторы не содержат каких-либо данных, вы можете просто написать функцию.Например, std::endl
реализован примерно так (ему нужно также справиться с широкими потоками и, таким образом, нужно что-то волшебное, чтобы организовать преобразование символов):
std::ostream& endl(std::ostream& out) {
(out << '\n').flush();
return out;
}
Если ваши манипуляторы имеют некоторые данные, которые вынеобходимо сохранить данные в подходящем объекте, а затем просто создать нормальный оператор вывода для этого класса, например, std::setw()
может быть реализовано следующим образом (опять же, игнорируя, что потоки на самом деле являются шаблонами):
struct std::setw {
setw(int size): size_(size) {}
int size_;
};
std::ostream& operator<< (std::ostream& out, std::setw const& object) {
out.width(object.size_);
return out;
}
Вы можете реализовать операторы вывода в качестве члена, потому что вы не управляете левой стороной operator<<()
: здесь находится объект потока.Если бы вы реализовывали std::ostream
, вы могли бы реализовать эти члены (ну, на самом деле, стандартные требования, согласно которым определенные операторы вывода являются членами std::ostream
).