I'm currently using the very clever package boost::const_string until http://libcxx.llvm.org/ is available pre-packaged on Ubuntu or GCC make its __versa_string (in header ext/vstring.h) its default string implementation. libcxx's std::string aswell as __versa_string uses _small-string optimization (SSO) by default. Default support for outputting to an std::ostream is lacking however. The code
#include <iostream>
#include <boost/const_string.hpp>
const_string<char> x;
std::cout << x << endl;
does not work unless we force x into a c-string via c_str() which becomes
std::cout << x.c_str() << endl;
which compiles and works as expected. I added the following line to const_string.hpp
template <typename T>
inline std::ostream & operator << (std::ostream & os, const boost::const_string<T> & a)
{
return os.write(a.data(), a.size());
}
This should improve performance over x.c_str() because size() is already known and does not need to be calculated by searching for NULL as in c_str(). I works for me but I am uncertain whether it works all cases. Have I missed something?
Have I missed something?
Yes, just include const_string/io.hpp. All it does however is:
return o << std::basic_string<char_type, traits_type>(s.data(), s.size());
It seems that this could have implications based on the locale and/or facets applied to the stream for strings vs just writing the straight data as you're doing.
It would be less performant, but what about creating a std::string from the const_string and using << to insert that into the stream?
No (you have not missed anything, afaik). If your aim is not to copy over content, str.data() is the way to go.
Related
I've been working on a personal dictionary application which can help you remembering words you learnt. It is operated via the CLI (just don't question this, it's kinda just a test and I got a weird passion for CLI apps). So, of course I am using ostreams for writing information on the CLI. I am used to write operator<< overloads (for ostreams) for every class so that I can build up a multi-level output system (basically every object can "speak" for itself).
In order to persist a dictionary object, I wanted to use ofstream and write a file with it. Naturally, I wrote operator<< overloads also for ofstream and in the same "layered" structure.
As a result, I have now two operator<< overloads in every class, like in "Dictionary":
ostream& operator<<(ostream&, const Dictionary&);
ofstream& operator<<(ofstream&, const Dictionary&);
(this is just the declaration in the header file)
Notice that it is very important that these both overloads do different things. I don't want to have some weird persistence-oriented special-format text on the CLI and also not user-friendly plain text in my file.
The problem is that, because of the inheritance structure of ostream and ofstream, ofstream is sometimes implicitely converted to ostream. And when this happens in the middle of my stack full of file output operations, the program suddenly jumps into the wrong overload and prints plain text in the file.
My question is simply: Is there a way to avoid or revert these unwanted implicit conversions in order to let my program jump into the right overloads? Or is there any other good way to fix this problem?
EDIT 1:
Someone pointed out in the comments that this is not an implicit converison. ofstream is sometimes "seen" as its base class ostream. The problem is that at some point the object "forgets" that it is an ofstream and loses all file-related information. From there on it is only an ostream and that's what I meant with the "conversion".
EDIT 2:
The exact point in the program where the "unwanted conversion" happens can be found here:
ofstream& operator<<(ofstream& of, const Section& s) {
return s.print_ofstream(of);
}
So this operator overoad calls "print_ofstream":
ofstream& Section::print_ofstream(ofstream& of) const {
of << "sec" << Util::ID_TO_STRING(section_id) << ":\n";
for (pair<Wordlist, Wordlist> pwl : translations) {
of << '{' << pwl.first << '=' << pwl.second << "}\n";
}
of << "#\n";
return of;
}
Note that "pwl" is a pair of two Wordlists, therefore pwl.first / pwl.second is a Wordlist. So, normally the line of << '{' << pwl.first << '=' << pwl.second << "}\n"; should call the ofstream operator<< overload in Wordlist. But it doesn't. Instead, the other overload method is called:
ostream& operator<<(ostream& o, const Wordlist& wl) {
return wl.print_ostream(o);
}
You have overloaded only the specific operator<< needed for streaming Dictionary, Section, Wordlist, etc objects to a std::ofstream, but std::ofstream inherits MANY other operator<<s from std::ostream, and those operators all take ostream& as input and return ostream& as output. So, for example, of << "sec" will return ostream& even though of is a std::ofstream, and then that ostream& is used for subsequent << calls until ; is reached. Those are the "implicit conversions" you are experiencing.
The real question is, WHY do you want operator<< to output different data depending on the type of std::ostream being written to? That goes against C++'s streaming model. If you really want that, you would have to change print_ofstream(ofstream&) to print_ostream(ostream&) and then dynamically detect the actual std::ostream derived type using dynamic_cast. Same with Wordlist, and any other classes that need it.
A simpler and safer option would be to just store a flag inside of your classes to control how their data should be output, regardless of the type of std::ostream being used. Then you can set that flag as needed. Maybe even define some helper I/O manipulators to set those flags while making << calls.
I have the following mock up code of a class which uses an attribute to set a filename:
#include <iostream>
#include <iomanip>
#include <sstream>
class Test {
public:
Test() { id_ = 1; }
/* Code which modifies ID */
void save() {
std::string filename ("file_");
filename += getID();
std::cout << "Saving into: " << filename <<'\n';
}
private:
const std::string getID() {
std::ostringstream oss;
oss << std::setw(4) << std::setfill('0') << id_;
return oss.str();
}
int id_;
};
int main () {
Test t;
t.save();
}
My concern is about the getID method. At first sight it seems pretty inefficient since I am creating the ostringstream and its corresponding string to return. My questions:
1) Since it returns const std::string is the compiler (GCC in my case) able to optimize it?
2) Is there any way to improve the performance of the code? Maybe move semantics or something like that?
Thank you!
Creating an ostringstream, just once, prior to an expensive operation like opening a file, doesn't matter to your program's efficiency at all, so don't worry about it.
However, you should worry about one bad habit exhibited in your code. To your credit, you seem to have identified it already:
1) Since it returns const std::string is the compiler (GCC in my case) able to optimize it?
2) Is there any way to improve the performance of the code? Maybe move semantics or something like that?
Yes. Consider:
class Test {
// ...
const std::string getID();
};
int main() {
std::string x;
Test t;
x = t.getID(); // HERE
}
On the line marked // HERE, which assignment operator is called? We want to call the move assignment operator, but that operator is prototyped as
string& operator=(string&&);
and the argument we're actually passing to our operator= is of type "reference to an rvalue of type const string" — i.e., const string&&. The rules of const-correctness prevent us from silently converting that const string&& to a string&&, so when the compiler is creating the set of assignment-operator functions it's possible to use here (the overload set), it must exclude the move-assignment operator that takes string&&.
Therefore, x = t.getID(); ends up calling the copy-assignment operator (since const string&& can safely be converted to const string&), and you make an extra copy that could have been avoided if only you hadn't gotten into the bad habit of const-qualifying your return types.
Also, of course, the getID() member function should probably be declared as const, because it doesn't need to modify the *this object.
So the proper prototype is:
class Test {
// ...
std::string getID() const;
};
The rule of thumb is: Always return by value, and never return by const value.
1) Since it returns const std::string is the compiler (GCC in my case)
able to optimize it?
Makes no sense to return a const object unless returning by reference
2) Is there any way to improve the performance of the code? Maybe move
semantics or something like that?
Id id_ does not change, just create the value in the constructor, using an static method may help:
static std::string format_id(int id) {
std::ostringstream oss;
oss << std::setw(4) << std::setfill('0') << id;
return oss.str();
}
And then:
Test::Test()
: id_(1)
, id_str_(format_id(id_))
{ }
Update:
This answer is not totally valid for the problem due to the fact that id_ does change, I will not remove it 'cause maybe someone will find it usefull for his case. Anyway, I wanted to clarify some thoughts:
Must be static in order to be used in variable initialization
There was a mistake in the code (now corrected), which used the member variable id_.
It makes no sense to return a const object by value, because returning by value will just copy (ignoring optimizations) the result to a new variable, which is in the scope of the caller (and might be not const).
My advice
An option is to update the id_str_ field anytime id_ changes (you must have a setter for id_), given that you're already changin the member id_ I assume there will be no issues updating another.
This approach allows to implement getID() as a simple getter (should be const, btw) with no performance issues, and the string field is computed only once.
One possibility would be to do something like this:
std::string getID(int id) {
std::string ret(4, '0') = std::to_string(id);
return ret.substring(ret.length()-4);
}
If you're using an implementation that includes the short string optimization (e.g., VC++) chances are pretty good that this will give a substantial speed improvement (a quick test with VC++ shows it at around 4-5 times as fast).
OTOH, if you're using an implementation that does not include short string optimization, chances are pretty good it'll be substantially slower. For example, running the same test with g++, produces code that's about 4-5 times slower.
One more point: if your ID number might be more than 4 digits long, this doesn't give the same behavior--it always returns a string of exactly 4 characters rather than the minimum of 4 created by the stringstream code. If your ID numbers may exceed 9999, then this code simply won't work for you.
You could change getID in this way:
std::string getID() {
thread_local std::ostringstream oss;
oss.str(""); // replaces the input data with the given string
oss.clear(); // resets the error flags
oss << std::setw(4) << std::setfill('0') << id_;
return oss.str();
}
it won't create a new ostringstream every single time.
In your case it isn't worth it (as Chris Dodd says opening a file and writing to it is likely to be 10-100x more expensive)... just to know.
Also consider that in any reasonable library implementation std::to_string will be at least as fast as stringstream.
1) Since it returns const std::string is the compiler (GCC in my case)
able to optimize it?
There is a rationale for this practice, but it's essentially obsolete (e.g. Herb Sutter recommended returning const values for non-primitive types).
With C++11 it is strongly advised to return values as non-const so that you can take full advantage of rvalue references.
About this topic you can take a look at:
Purpose of returning by const value?
Should I return const objects?
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.
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 was messing around with std::ostringstream whilst looking at this question: sprintf in c++?, and noticed the stringbuilder() wrapper by Nawaz and thought, well that ought to work with std::ostringstream.
So my first attempt was the following:
std::cout << (std::ostringstream("select * from foo limit") << max_limit).str() << std::endl;
Now this obviously fails to compile (correctly) as the result of the operator<< is a std::ostream - which doesn't have the member str(). So I thought a cast should do the trick, and specifically a cast to a const reference (works with a cast to a normal reference too), so second attempt:
std::cout << static_cast<std::ostringstream const&>(std::ostringstream("select * from foo limit") << max_limit).str() << std::endl;
Now this compiles fine and runs, however the output is, well, not what I was expecting.
10lect * from foo limit
Now - here's the question, am I invoking some undefined behaviour somewhere - and if so where? And how is this different to the approach that Nawaz has taken (I guess aside from the result of his operator is the stringbuilder itself rather than std::ostream).
EDIT: here is the ideone code.
EDIT: oops - forgot to specify, max_limit is int.
You need to move the stream's position to the end of the internal buffer used by ostringstream:
std::ostringstream out("select * from foo limit ", std::ios_base::app);
out << max_limit;
std::cout << out.str () << std::endl;
See the documentation on ostringstream constructor.
What's maxLimit?
Some of the ostream operator<< overloads are free functions, like:
ostream& operator<<(ostream& os, T const&);
If the stream is a temporary (which in your case it is), it cannot bind to that ref-to-non-const, and the overload cannot be chosen.
So you may be using a non-preferred overload by accident; possibly something like the overload for char const*. Hard to tell without knowing what maxLimit is.
This is a limitation when trying to do this serialisation on a single line, and you can't get around it.
You're also attempting to stream std::cout to std::cout, which is obviously not what you intended to do.
Update Vijay figured it out.
std::cout << static_cast<std::ostringstream const&>(
std::ostringstream("select * from foo limit", std::ios_base::app) << max_limit
).str() << std::endl
The above is still definitely worth bearing in mind, though.
You could also simply use flush as:
static_cast<std::ostringstream const&>(std::ostringstream().flush() << "select * from foo limit " << max_limit).str() << std::endl;
But then the code is not same. Its using default constructor.
As a sidenote : isn't dynamic_cast more appropriate here?
Demo : http://www.ideone.com/06xNS