In C++, using operator<< to construct input for a function - c++

I would like to be able write code that looks like this:
int n;
std::string s = "some string";
SomeFunction("hello world" << n << " " << s << std::endl);
Where SomeFunction() is a method of some other class. The point is that I would like to be able to construct input for certain method using operator<<, just the way one'd do when writing to standard output in C++. How can I do that?
Thanks.

Your first parameter would have to be a home-made type that overloads operator<< and builds some kind of parameter list.
Your class would probably contain an ostream and would forward the operator<< to it.
If the function takes a string rather than your mysterious string-building object, you would then need to convert your object back to a string.
You could do it aleady with ostringstream like this:
int n;
std::string s;
std::ostringstream oss;
SomeFunction( ( oss << "hello world " << n << " " << s << '\n' ).str() );

Thanks, but this solution is way too obvious. I am looking for the code to remain the same as in the sample. – Alexander Sandler 54 secs ago
A surprising bias against obvious solutions?
Your syntax just cannot be achieved (in general[1]) without the macro that you describe in the first comment. Period.
[1] In specific cases you might be able to force the issue by overloading to ostream& operator<<(std::string, myspecifictype). In practice this will give you nothing but headaches because just about every use of the << operator will subsequently result in ambiguous overload resolutions

Related

Write a string to char while passing arguments to the string

I have the following code:
char szBuf[256] = "";
std::string szFmt = "You have recieved %s item."
string szName = "Fork";
snprintf(szBuf, sizeof(szBuf), szFmt.c_str(), szName);
I'm trying to combine szFmt with szBuf while combining szFmt with szName according to.However, when I execute this code in win10, I getting such an weird output:
You've received the LÃý item.
And when I try to execute the code in OSX El Capitan, I'm getting the following error
cannot pass object of non-trivial type 'string' throgh variadic function;
call will about at runtime
So what is the problem, and how can I solve this?
Note: I checked this question, but in the answer, they are passing directly "Fork", which also works in me; however it doesn't work when I pass it as szName.
Better solutions were mentioned in the comments (ostringstream) but for further educational value, I'll address the immediate problem here.
Varargs (the mechanism through which the printf family of functions can accept a variable number of arguments) are not as strictly type checked as the rest. In this case, snprintf is expecting a char* to the string, but you're passing szName which is a string object. So you need to call .c_str() on that as well:
snprintf(szBuf, sizeof(szBuf), szFmt.c_str(), szName.c_str());
Using std::ostringstream will simplify things, especially since it's more type-safe than the printf functions inherited from C, but also since it can handle all standard types and with proper overloading of the output operator << you can also use it very easily for custom classes.
The important thing to remember with std::ostringstream is that it is an ordinary output stream, just like std::cout, and if you can use std::cout then you can also use std::ostringstream (or any other standard output stream).
Now for how to use it:
std::ostringstream ostr; // Define the stream object
ostr << "You have recieved " << szName << " item.";
And that's about it.
To access the string you use the str function:
std::cout << "The output is " << ostr.str() << '\n';
And if you want to copy it into a char buffer for some reason:
// Use `strncpy` to not overflow the destination buffer
std::strncpy(szBuf, ostr.str().c_str(), sizeof szBuf - 1);
// Remember that `strncpy` might not terminate the destination, so do it explicitly
szBuf[sizeof szBuf - 1] = '\0';

Handling variable data using << operator

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))}
};

C++: Is it possible to get a std::string out of an object that overloads the << operator?

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.

Odd(?) behaviour of a temporary std::ostringstream

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

Transparently manipulating strings inserted into an ostream

I'd like to provide an std::ostream that may or may not, from the user's point of view, encrypt its contents.
Imagine some random function that uses an std::ostream&:
void write_stuff( std::ostream& stream ) {
os << "stuff";
}
Whether stuff is output in cleartext or is encrypted is dependent on how the stream argument was initialized.
I'm thinking about inheriting from std::basic_streambuf, but I'm not sure it's the best way to go. I think the ideal scenario is some sort of filter object which is run before the contents are actually output. That way it'd be easy to chain operations, e.g. encrypting and then hex-encoding, which is a benefit that making my own basic_streambuf does not seem to give (not easily at least).
Any advices?
Thanks.
UPDATE: I followed the strategy laid out by the accepted answer. I found this article on writing a custom streambuf which performs XOR obfuscation to be extremely helpful as a starting point.
A streambuf can be implemented in terms of another arbitrary streambuf that's either passed in as an argument to the constructor or set with a special member function. And that allows you to stack streambuf implementations like you were thinking of.
You could even make a manipulator that uses the ostream's rdbuf function to get the current streambuf, call a function on your streambuf that sets the 'stacked' streambuf, and then calls rdbuf again to replace the ostream's streambuf with your own.
aes_ctr_streambuf encrypter(key);
zlib_streambuf compressor;
::std::cout << stack_streambuf(encrypter) << stack_streambuf(compressor);
It is hard to describe in short what you have to do in order to create an I/O stream for the new source or sink. Luckily, Jonathan Turkanis and CodeRage, LLC have created very nice building blocks with exceptional documentation that can help you save hundreds of hours of research and development of new streams. The library is called Boost.Iostreams.
The second example in documentation exactly shows how to solve your problem.
Also, note that they already have an output stream with zip compression. So maybe you don't even need to write a single line of code.
Good luck!
I'm not sure that what I'm about to suggest is exactly what you need (and its too complicated to be a comment), but have you ever heard of the stream manipulators ?
#include <iostream>
#include <iomanip>
int main(int, char**)
{
int a = 10;
std::cout << "a: " << a << std::endl; //outputs: "a: 10"
std::cout << "a: " << std::hex << a << std::endl; //outputs: "a: a"
std::cout << "a: " << std::dec << a << std::endl; //outputs: "a: 10"
return EXIT_SUCCESS;
}
You may indeed use a similar pattern (this matches what you actually call a "filter" object) to somehow change the state of your custom stream object.