Важные примечания из комментариев ниже:
Мартин:
@Chareles: Тогда по этому требованию все манипуляторы являются липкими. За исключением setw, который, кажется, сбрасывается после использования.
Чарльз:
Совершенно верно! и единственная причина, по которой setw, похоже, ведет себя иначе, заключается в том, что существуют требования к операциям форматированного вывода для явного .width (0) потока вывода.
Ниже приводится обсуждение, которое приводит к приведенному выше выводу:
Глядя на В коде следующие манипуляторы возвращают объект, а не поток:
setiosflags
resetiosflags
setbase
setfill
setprecision
setw
Это обычный метод применения операции только к следующему объекту, который применяется к потоку. К сожалению, это не мешает им быть липкими. Тесты показывают, что все они, кроме setw
, липкие.
setiosflags: Sticky
resetiosflags:Sticky
setbase: Sticky
setfill: Sticky
setprecision: 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 кажется единственным манипулятором в моей версии, который не является липким.
Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:
Таким образом, любая информация о состоянии, которую они изменяют, должна быть записана в объект потока и, таким образом, является постоянной (до тех пор, пока другой манипулятор не изменит состояние). Таким образом, следующие манипуляторы должны быть липкими манипуляторами.
[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 кажется единственным манипулятором в моей версии, который не является липким.
Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:
Таким образом, любая информация о состоянии, которую они изменяют, должна быть записана в объект потока и, таким образом, является постоянной (до тех пор, пока другой манипулятор не изменит состояние). Таким образом, следующие манипуляторы должны быть липкими манипуляторами.
[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, кажется, единственный манипулятор в моей версии, который не является липким.
Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:
[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 кажется единственным манипулятором в моей версии, который не является липким.
Для Чарльза простой трюк, влияющий только на следующий элемент в цепочке:
[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
Причина того, что width
не кажется «липким», заключается в том, что определенные операции гарантированно вызывают .width (0)
в выходном потоке. Это:
21.3.7.9 [lib.string.io]:
template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
const basic_string<charT,traits,Allocator>& str);
22.2.2.2.2 [lib.facet.num.put.virtuals]: все do_put
перегрузки для num_put
шаблон. Они используются перегрузками оператора <<
, принимающими basic_ostream
и встроенный числовой тип.
22.2.6.2.2 [lib.locale.money.put.virtuals] : Все перегрузки do_put
для шаблона money_put
.
27.6.2.5.4 [lib.ostream.inserters.character]: Перегрузки оператора <<
беря basic_ostream
и один из типов char экземпляра basic_ostream или char
, signed char
или unsigned char
или указатели на массивы этих типов char.
Честно говоря, я не уверен в обосновании этого, но никаких других состояний ostream
должен быть сброшен функциями форматированного вывода. Конечно, такие вещи, как badbit
и failbit
, могут быть установлены в случае сбоя в операции вывода, но этого следовало ожидать.
Единственная причина, которую я могу придумать. для сброса ширины может быть удивительно, если при попытке вывести некоторые поля с разделителями ваши разделители были дополнены.
Например
std::cout << std::setw(6) << 4.5 << '|' << 3.6 << '\n';
" 4.5 | 3.6 \n"
Чтобы «исправить» это потребует:
std::cout << std::setw(6) << 4.5 << std::setw(0) << '|' << std::setw(6) << 3.6 << std::setw(0) << '\n';
тогда как при сбросе ширины желаемый результат может быть сгенерирован с помощью более короткого:
std::cout << std::setw(6) << 4.5 << '|' << std::setw(6) << 3.6 << '\n';
setw ()
влияет только на следующую вставку. Именно так ведет себя setw ()
. Поведение setw ()
такое же, как ios_base :: width ()
. Я получил информацию о setw ()
с cplusplus.com .
Вы можете найти полный список манипуляторов здесь . По этой ссылке все флаги потока должны быть установлены, пока не будут изменены другим манипулятором. Одно замечание о левом
, правом
и внутреннем
манипуляторах: они похожи на другие флаги, и действительно сохраняются, пока не будут изменены. Однако они действуют только в том случае, если задана ширина потока, а ширина должна задаваться для каждой строки. Так, например,
cout.width(6);
cout << right << "a" << endl;
cout.width(6);
cout << "b" << endl;
cout.width(6);
cout << "c" << endl;
даст вам
> a
> b
> c
, а
cout.width(6);
cout << right << "a" << endl;
cout << "b" << endl;
cout << "c" << endl;
даст вам
> a
>b
>c
Манипуляторы ввода и вывода не являются липкими и появляются только один раз там, где они используются. Все параметризованные манипуляторы отличаются друг от друга, вот краткое описание каждого:
setiosflags
позволяет вам вручную устанавливать флаги, список которых можно найти здесь , так что он липкий.
Resetiosflags
ведет себя аналогично setiosflags
, за исключением того, что он сбрасывает указанные флаги.
setbase
устанавливает базу целых чисел, вставленных в поток (таким образом, 17 в базе 16 будет «11», а в базе 2 будет «10001»).
setfill
устанавливает символ заполнения для вставки в поток, когда используется setw
.
setprecision
устанавливает десятичную точность, которая будет использоваться при вставке значений с плавающей запятой.
setw
выполняет только следующую вставку указанной ширины, заполняя символом, указанным в setfill