Wichtige Hinweise aus den Kommentaren unten:
Von Martin:
@ Charles: Dann sind durch diese Anforderung alle Manipulatoren klebrig. Außer setw, das nach Gebrauch zurückgesetzt zu werden scheint.
Von Charles:
Genau! und der einzige Grund, warum sich setw anders zu verhalten scheint, ist, dass es Anforderungen an formatierte Ausgabeoperationen gibt, um den Ausgabestream explizit mit .width (0) zu versehen.
Das Folgende ist die Diskussion, die zu der obigen Schlussfolgerung führt:
Wenn Sie sich den Code ansehen, geben die folgenden Manipulatoren eher ein Objekt als einen Stream zurück:
setiosflags
resetiosflags
setbase
setfill
setprecision
setw
Dies ist eine übliche Technik, um eine Operation nur auf das nächste Objekt anzuwenden, das auf den Stream angewendet wird. Leider schließt dies nicht aus, dass sie klebrig sind. Tests zeigen, dass alle außer setwklebrig sind.
setiosflags: Sticky
resetiosflags:Sticky
setbase: Sticky
setfill: Sticky
setprecision: Sticky
Alle anderen Manipulatoren geben ein Stream-Objekt zurück. Daher müssen alle Statusinformationen, die sie ändern, im Stream-Objekt aufgezeichnet werden und sind somit permanent (bis ein anderer Manipulator den Status ändert). Daher müssen die folgenden Manipulatoren Sticky- Manipulatoren sein.
[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase
dec/ hex/ oct
fixed/ scientific
internal/ left/ right
Diese Manipulatoren führen tatsächlich eine Operation für den Stream selbst und nicht für das Stream-Objekt aus (obwohl der Stream technisch gesehen Teil des Status der Stream-Objekte ist). Ich glaube jedoch nicht, dass sie einen anderen Teil des Status der Stream-Objekte beeinflussen.
ws/ endl/ ends/ flush
Die Schlussfolgerung ist, dass setw der einzige Manipulator in meiner Version zu sein scheint, der nicht klebrig ist.
Für Charles ein einfacher Trick, um nur das nächste Element in der Kette zu beeinflussen:
Hier ist ein Beispiel, wie ein Objekt verwendet werden kann, um den Status vorübergehend zu ändern und ihn dann mithilfe eines Objekts zurückzusetzen:
#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