Важные заметки из комментариев ниже:
Мартин:
@ Chareles: Тогда по этому требованию все манипуляторы являются липкими. За исключением setw, который, кажется, сбрасывается после использования.
Чарльз:
Точно! и единственная причина, по которой setw, по-видимому, ведет себя по-разному, состоит в том, что для форматированных операций вывода существуют явные требования .width (0) потока вывода.
Ниже приводится обсуждение, которое привело к приведенному выше выводу:
Глядя на код, следующие манипуляторы возвращают объект, а не поток:
setiosflags
resetiosflags
setbase
setfill
setprecision
setw
Это обычная техника для применения операции только к следующему объекту, который применяется к потоку. К сожалению, это не мешает им быть липкими. Испытания показывают, что все они, кроме setw
, липкие.
setiosflags: Sticky
resetiosflags:Sticky
setbase: Sticky
setfill: Sticky
setprecision: Sticky
Все остальные манипуляторы возвращают объект потока. Таким образом, любая информация о состоянии, которую они изменяют, должна быть записана в объекте потока и, таким образом, является постоянной (пока другой манипулятор не изменит состояние). Таким образом, следующие манипуляторы должны быть Sticky манипуляторов.
[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase
dec/ hex/ oct
fixed/ scientific
internal/ left/ right
Эти манипуляторы фактически выполняют операцию с самим потоком, а не с объектом потока (хотя технически поток является частью состояния объектов потока). Но я не верю, что они влияют на любую другую часть состояния потоковых объектов.
ws/ endl/ ends/ flush
Вывод таков: setw, кажется, единственный манипулятор в моей версии, который не является липким.
Для Чарльза простой трюк затрагивает только следующий элемент в цепочке:
Вот пример того, как объект может быть использован для временного изменения состояния, а затем его возврата с помощью объекта:
#include <iostream>
#include <iomanip>
// Private object constructed by the format object PutSquareBracket
struct SquareBracktAroundNextItem
{
SquareBracktAroundNextItem(std::ostream& str)
:m_str(str)
{}
std::ostream& m_str;
};
// New Format Object
struct PutSquareBracket
{};
// Format object passed to stream.
// All it does is return an object that can maintain state away from the
// stream object (so that it is not STICKY)
SquareBracktAroundNextItem operator<<(std::ostream& str,PutSquareBracket const& data)
{
return SquareBracktAroundNextItem(str);
}
// The Non Sticky formatting.
// Here we temporariy set formating to fixed with a precision of 10.
// After the next value is printed we return the stream to the original state
// Then return the stream for normal processing.
template<typename T>
std::ostream& operator<<(SquareBracktAroundNextItem const& bracket,T const& data)
{
std::ios_base::fmtflags flags = bracket.m_str.flags();
std::streamsize currentPrecision = bracket.m_str.precision();
bracket.m_str << '[' << std::fixed << std::setprecision(10) << data << std::setprecision(currentPrecision) << ']';
bracket.m_str.flags(flags);
return bracket.m_str;
}
int main()
{
std::cout << 5.34 << "\n" // Before
<< PutSquareBracket() << 5.34 << "\n" // Temp change settings.
<< 5.34 << "\n"; // After
}
> ./a.out
5.34
[5.3400000000]
5.34