This is a exercise for school, so please provide just hints and no complete examples ;-)
I have my own manipulator:
template<typename T, typename Tr=char_traits<T> >
ios_base& toggle(basic_ios<T,Tr>& io)
{
if(io.flags() & ios::scientific)
{ io.unsetf(ios::scientific); io.flags(ios::fixed); }
else { io.unsetf(ios::fixed); io.flags(ios::scientific); }
return io;
}
I wrote this, because I have to write a manipulator with the form ios_base& my_manip(basic_ios&).
If I use it like this (without using return value):
toggle(cout);
... that works fine. But if I use it like that:
toggle(cout) << 54444.6456555 << endl;
That does not work (Because std::ios_base does not have operator<<() as stated below).
In general I do not get what ios_base& my_manip(basic_ios&) could be useful for... Do you have a hint/example?
You guys already helped me a lot! What I still do NOT understand, is the motivation to pass a basic_ios and give back ios_base (because that is suggested to do in the exercise I have to solve...). What could be a possible scenario to use this???
The problem with the manipulator is that it returns an std::ios_base& rather than a std::ostream& you can write to. You could change the manipulator to take an std::ostream& as parameter and return the reference received. However, the output stream class defines output operators which take pointers to functions:
std::ostream& std::ostream::operator<< (std::ios_base& (*)(std::ios_base&)) { ... }
That is, you can just insert manipulators pretty much the way you would do it with, e.g., std::hex:
std::cout << std::hex << 123 << ' ' << std::dec << 123 << '\n';
In addition to the issue which Dietmar addressed: io.flags()
& ios::scientific does not return a bool, and the conversion
to bool probably doesn't do what you want. You need something
along the lines of:
if ( (io.flags() & ios::floatfield) == ios::fixed ) {
io.setf( ios::scientific, ios::floatfield );
} else if ( (io.flags() & ios::floatfield) == ios::scientific ) {
io.setf( ios::fixed, ios::floatfield );
} else {
// Whatever you want to happen first time around...
}
Despite being part of a variable with a type named ...flags,
floatfield is not a flag, but a field which can take on at
least three values: fixed, scientific and its default value
in which neither of these are set. (basefield and
adjustfield behave similarly.)
Note too the use of the two argument form of ios::setf; it is
designed especially for these bitfield format parameters, and
resets the bits in its second argument before setting the ones
in its first.
I might add that you probably do not want to call io.flags
in your manipulator; this sets all of the formatting flags to
the value you give, effectively resetting all other formatting
flags. If you're only outputting floating point, this may not
be a problem (although showpos, showpoint, uppercase and
possibly unitbuf might be relevant), but you never know.
Related
I have a piece of code for sending data to remote side, it is acting a little like picojson, for example:
server::value::object obj;
obj["cmd"] = server::value("test");
obj["url"] = server::value(url);
...
obj["code"] = server::value(std::to_string(code));
server::value v(obj);
client.send_to_server(v.process());
As long as there is something to send, there will be a block like this.
These lines are used in so many places in my project that I'm thinking of using a function or << operator to replace it, which should be able to handle variable arguments.
A << operator version would be like:
Data d << "cmd" << "test"
<< "url" << url
<< ... << ...
<< "code" << code;
client.send_to_server(d);
Is this a good idea doing so? How to implement it?
Thanks.
I would write it differently:
d << add_value("cmd", "test")
<< add_value("url", url)
<< add_value(..., ...)
<< add_value("code", code)
;
Why? It's clearer and allows better type control.
So you create a class, say __add_value_temp which holds both the name and the value, a function add_value that creates this class, and write a << operator
Data &operator<<(Data &d, const __add_value_temp &val){
d.add(val.name,val.val);
return d;
}
Better yet - instead of __add_value_temp you can use an std::pair, and use std::make_pair instead of add_value!
Data &operator<<(Data &d, const std::pair<std::string,std::string> &val){
d.add(val.first,val.second);
return d;
}
...
Data d;
d << std::make_pair("cmd", "test")
<< std::make_pair("url", url)
<< std::make_pair(..., ...)
<< std::make_pair("code", code)
;
(last note: might be smart to write the operator<< templated on the types of the pair, so that you can pass things by reference and generally maybe avoid unneeded copying)
Designing an API like that is not a good idea, because it is extremely error-prone.
A seemingly similar idea worked fine with output streams for a simple reason: the data that you put into the stream for output is treated uniformly. Anything that you put into << as an argument becomes part of the output, apart from stream manipulators, which control how the output is to be presented.
Your API is different: odd items are treated differently from the even ones. Moreover, it is a mistake to send an odd total number of operands. If for some reason you forget to put a string code on one of the lines, all values would silently become codes on the subsequent lines. Such API is very fragile, so I would strongly recommend agains it.
I think an API that lets your users add items in pairs would work better. If your compiler is C++11 compliant, you could also use uniform initialization syntax:
Data d = {
{"cmd", server::value("test")}
, {"url", server::value(url)}
, {"code", server::value(std::to_string(code))}
};
It seems to me that defining the << operator (operator<<) to work directly with strings is more elegant than having to work with ostringstreams and then converting back to strings. Is there a reason why c++ doesn't do this out of the box?
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
template <class T>
string& operator<<(string& s, T a) {
ostringstream ss;
ss << a;
s.append(ss.str());
return s;
}
int main() {
string s;
// this prints out: "inserting text and a number(1)"
cout << (s << "inserting text and a number (" << 1 << ")\n");
// normal way
ostringstream os;
os << "inserting text and a number(" << 1 << ")\n";
cout << os.str();
}
Streams contain additional state. Imagine if this were possible:
std::string str;
int n = 1234;
str << std::hex;
str << n;
return str; // returns "0x4d2" (or something, I forget)
In order to maintain this additional state, strings would have to have storage for this state. The C++ standards committee (and C++ programmers in general) have generally frowned upon superfluous resource consumption, under the motto "pay only for what you use". So, no extra fields in the string class.
The subjective answer: is that I think the std::string class was quite poorly designed to begin with, especially compared to other parts of C++'s excellent standard library, and adding features to std::string is just going to make things worse. This is a very subjective opinion and feel free to dismiss me as a raving lunatic.
The problem with the idea of strings being output streams is that they would become too heavy.
Strings are intended to "hold string data", not to format some output. Output streams have a heavy "state" which can be manipulated (see <iomanip>) and thus has to be stored. This means that, of course, this has to be stored for every string in every program, but almost none of them are used as an output stream; so it's a huge waste of resources.
C++ follows the "zero overhead" design principle (or at least no more overhead than totally necessary). Not having a string class which doesn't add any unnecessary overhead would be a huge violation of this design principle. If this was the case: what would people do in overhead-critical cases? Use C-strings... ouch!
In C++11, an alternative is to use the operator+= with std::to_string to append to a string, which can also be chained like the operator<< of the output stream. You can wrap both += and to_string in a nice operator<< for string if you like:
template <class Number>
std::string& operator<<(std::string& s, Number a) {
return s += std::to_string(a);
}
std::string& operator<<(std::string& s, const char* a) {
return s += a;
}
std::string& operator<<(std::string& s, const std::string &a) {
return s += a;
}
Your example, updated using this method: http://ideone.com/4zbVtD
Probably lost in the depths of time now but formatted output was always associated with streams in C (since they didn't have "real" strings) and this may have been carried over into C++ (which was, after all, C with classes). In C, the way to format to a string is to use sprintf, a variation on fprintf, the output-to-stream function.
Obviously conjecture on my part but someone probably thought similarly to yourself that these formatting things in the streams would be brilliant to have on strings as well, so they subclassed the stream classes to produce one that used a string as it's "output".
That seems the elegant solution to getting it working as quickly as possible. Otherwise, you would have had formatting code duplicated in streams and strings.
In Visual C++, if I have a double with the value inf, and I output it using a stream:
double myval = std::numeric_limits<double>::infinity();
std::ostringstream msg;
msg << "This is infinite: " << myval;
The result is "1.#INF".
Is there an easy way to make it print simply "inf" or "INF"? This string appears in text that will subsequently be parsed, and extra characters are causing us problems.
I thought of overloading the stream operator for double, but double is a built-in type.
I confess I can't figure out exactly how to search for an answer to the basic question...
Thanks!
This is possible, but somewhat non-trivial, and the correct way to do it is fairly obscure.
As an aside, I'll note that when you do something like msg << myval; only one of the operands has to be a user-defined type, which is the case here (even though you didn't define it, an ostringstream is still officially a user-defined type). That's more or less irrelevant though. The existing overload of operator<< will work fine; you don't need to provide your own.
I think of a stream as a "matchmaker". You have a stream buffer to handle the actual I/O, and a locale to handle the formatting. Thinking of things that way, the solution becomes fairly clear: since what you want to change is the formatting, and formatting is handled by a locale, you need to change the locale.
A locale, however, is really a heterogeneous collection. Specifically, it's a collection of facet classes. In this case, the facet we care about is the num_put facet. The num_put facet class has virtual do_put member functions for various types. The one we care about in this case is double:
template <class charT, class OutputIterator = std::ostreambuf_iterator<charT> >
class num_put : public std::num_put<charT, OutputIterator> {
public:
virtual iter_type do_put(iter_type i,
std::ios_base& b,
char_type fill,
double v) const
{
if (v == std::numeric_limits<double>().infinity()) {
static const char inf[]="inf";
std::copy(std::begin(inf), std::end(inf), i);
}
else {
std::ostringstream temp;
temp << v;
std::copy(temp.str().begin(), temp.str().end(), i);
}
return i;
}
};
To use it, you imbue the stream in question with a locale that includes that facet:
int main() {
char *d="0";
std::locale loc(std::locale::classic(), new num_put<char>);
std::cout.imbue(loc);
std::cout << 1.0/atoi(d);
return 0;
}
I should add, however, that this was slapped together pretty quickly, and testing is extremely minimal. It works for the test case, and probably for other narrow streams. At a guess, it probably needs more work before it'll work correctly with a wide stream though.
I have an object that can be printed to the console with std::cout << obj, but I can't get a std::string out of it, because it doesn't seem to implement something like a .string() method. I thought I might be able to use that overloaded operator to just get string representations of everything instead of having to implement a function to do it myself every time I need it, though having found nothing on the subject makes me think this isn't possible.
Use a std::ostringstream. It is a C++ stream implementation which writes to a string.
You can use a std::ostringstream.
std::ostringstream os;
os << obj;
std::string result = os.str();
There are different ways of doing it, you can manually implement it in terms of std::ostringstream, or you can use a prepacked version of it in boost::lexical_cast. For more complex operations, you can implement a in-place string builder like the one I provided as an answer here (this solves a more complex problem of building generic strings, but if you want to check it is a simple generic solution).
It seems that the linked question has been removed from StackOverflow, so I will provide the basic skeleton. The first think is to consider what we want to use with the in-place string builder, which basically is avoiding the need to use create unnecessary objects:
void f( std::string const & x );
f( make_string() << "Hello " << name << ", your are " << age << " years old." );
For that to work, make_string() must provide an object that is able to take advantage of the already existing operator<< for the different types. And the whole expression must be convertible to std::string. The basic implementation is rather simple:
class make_string {
std::ostringstream buffer;
public:
template <typename T>
make_string& operator<<( T const & obj ) {
buffer << obj;
return *this;
}
operator std::string() const {
return buffer.str();
}
};
This takes care of most of the implementation with the very least amount of code. It has some shortcomings, for example it does not take manipulators (make_string() << std::hex << 30), for that you have to provide extra overloads that take the manipulators (function pointers). There are other small issues with this implementation, most of which can be overcome by adding extra overloads, but the basic implementation above is enough for most regular cases.
i have an overloaded operator << trying to make it work like this
mystream<<hex<<10;
i have overloaded method
mytream& operator<<(ios_base& (*m) ios_base&)
This gets called whenever hex is encountered cause the parameter passed in the method is a function pointer of type same as hex or like some other output manipulators like dec, oct.
i have two problems
1) how do i retrieve the parameter the hex would be operating on, in this example 10
2) how do i know that the << operator is being called for hex and not other manipulator function like oct and dec
Thanks
1) hex is not operating on the parameter 10. << operators associate left-to-right, which means your code is the same as:
(mystream<<hex)<<10;
So your overload has to return an object which, when 10 is shifted into it, prints in hex (or if not prints, writes data somewhere). As everyone says, this is done by saving flags in the stream object itself, then returning *this. The reason flags are used is precisely because the "10" is not available yet, since the second << has not been evaluated yet. The first << operator call cannot print anything - it just has to get ready for when the second one is called.
2) hex is a function. It can be compared with other functions:
ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
if (m == hex) {
} else if (m == oct) {
} else if (m == dec) {
}
}
Except you don't normally want to do that, you want the default behaviour, which is something like:
ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
return m(s);
}
(I may be wrong on that, I've never looked at the implementation, but the general idea is that the operator calls the manipulator function, and the manipulator (the clue's in the name) manipulates the stream).
std::hex sets the std::ios::hex format flag on its parameter. Then in your operator<<(int) override, if you have one, check the format flags by calling flags().
3) Manipulators which take paramers are functions too, but their return types are unspecified, meaning it's up to the implementation. Looking at my gcc iomanip header, setw returns _Setw, setprecision returns _Setprecision, and so on. The Apache library does it differently, more like the no-args manipulators. The only thing you can portably do with parameterized manipulators is apply them to an iostream with operator<<, they have no defined member functions or operators of their own.
So just like hex, to handle setw you should inherit from std::ios_base, rely on the operator<< implementation provided by your library, then when you come to format your data, examine your own width, precision, etc, using the width(), precision(), etc, functions on ios_base.
That said, if for some bizarre reason you needed to intercept the standard operator<< for these manipulators, you could probably bodge something together, along these lines:
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;
}
I do consider this a bodge, though. You're not really supposed to interfere with stream manipulators, just let your base class do the work and look up the results.
When operator<< gets called with hex or oct or dec, set a flag in your mystream object. When operator<< is called with a number, check to see if any of these flags are set. If so, convert the number to hex/octal/decimal and display it.
In answer to your second question, the parameter m is a pointer to the manipulator function. You can check that it's not null, then call that function, passing *this. hex() is as simple as setting a flag in the passed stream object, as Zifre suggested. Then when processing the integer, check if the flag in the stream object is set, and output accordingly.
This is how the standard library implements its manipulator functions.
In your example, hex operates on (changes the state of) the stream, not the following parameters. hex has no notion of, or any relation to other << calls.
Looking at how other io manipulators are implemented would go a long way to clearing things up.
You should be manipulating ios_base::flags
http://www.cplusplus.com/reference/iostream/ios_base/flags/
which is what the standard hex does.