1) hex не работает с параметром 10. Операторы <<
связывают слева направо, значит ваш код такой же как:
(mystream<<hex)<<10;
Таким образом, ваша перегрузка должна возвращать объект, который при смещении в него 10 печатает в шестнадцатеричном формате (или, если не печатает, записывает данные куда-то). Как все говорят, это делается путем сохранения флагов в самом объекте потока, а затем возврата *this
. Причина использования флагов заключается именно в том, что «10» еще недоступна, поскольку второй <<
еще не был оценен. Первый вызов оператора <<
не может ничего печатать - он просто должен быть готов к вызову второго.
2) hex — это функция. Его можно сравнить с другими функциями:
ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
if (m == hex) {
} else if (m == oct) {
} else if (m == dec) {
}
}
За исключением того, что вы обычно не хотите этого делать, вам нужно поведение по умолчанию, что-то вроде:
ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
return m(s);
}
(Возможно, я ошибаюсь, я никогда не смотрел на реализацию, но общая идея заключается в том, что оператор вызывает функцию манипулятора, а манипулятор (подсказка в названии) манипулирует потоком).
std::hex
устанавливает для своего параметра флаг формата std::ios::hex
. Затем в своем переопределении operator<<(int)
, если оно у вас есть, проверьте флаги формата, вызвав flags()
.
3) Манипуляторы, принимающие параметры, тоже являются функциями, но их возвращаемые типы не определены, то есть все зависит от реализации. Глядя на мой заголовок gcc iomanip
, setw
возвращает _Setw
, setprecision
возвращает _Setprecision
и так далее. Библиотека Apache делает это по-другому, больше похоже на манипуляторы без аргументов . Единственное, что вы можете переносимо сделать с параметризованными манипуляторами, — это применить их к iostream с operator<<
, у них нет определенных функций-членов или собственных операторов.
Так же, как hex
, для обработки setw
вы должны наследоваться от std::ios_base
, полагаться на реализацию operator<<
, предоставленную вашей библиотекой, затем, когда вы приступите к форматированию своих данных, проверьте свою собственную ширину, точность и т. д., используя width()
, precision()
и т. д. работает на ios_base
.
Тем не менее, если по какой-то странной причине вам нужно было перехватить стандартное operator<<
для этих манипуляторов, вы, вероятно, могли бы что-то сделать вместе, например:
template <typename SManip>
mystream &operator<<(mystream &s, SManip m) {
stringstream ss;
// set the state of ss to match that of s
ss.width(s.width());
ss.precision(s.precision());
// etc
ss << m;
// set the state of s to match that of ss
s.width(ss.width());
s.precision(ss.precision());
// etc
return s;
}
Хотя я считаю это бредом. На самом деле вы не должны вмешиваться в манипуляторы потока, просто позвольте вашему базовому классу выполнять работу и просматривать результаты.
person
Steve Jessop
schedule
16.07.2009