Passing Multiple Strings in Concatenation Attempt to an ostringstream Parameter - c++

I am trying to create a method that will accept a stream (i.e. ostringstream) parameter that will be logged to a file.
In the header file, it is declared as:
static void Log(const std::ostringstream& message, LoggingSeverity severity = LoggingSeverity::info);
However, when I try to call the method from another class, such as:
SimpleLogger::Log("Name registered.", SimpleLogger::LoggingSeverity::trace);
I am getting the following error: E0415 no suitable constructor exists to convert from "const char []" to "std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char>>"
And if I try to structure a call by concatenating strings (input is of type std::string), like this:
SimpleLogger::Log("String to int conversion of [" << input << "] failed.", SimpleLogger::LoggingSeverity::warning);
I receive the following error: E0349 no operator "<<" matches these operands
From the errors, I understand that the std::ostringstream parameter doesn't like the strings, but I was under the impression that the data type would provide me the needed functionality of being able to provide objects to the stream, including, for example, int values. Is there a better data type to achieve the desired result? Or, is the structured calls to the method incorrect?

Well the problem here is you are passing a string to a stringstram constructor, the idea is ok but the constructor is defined explicit so there is no automatic conversion to from string to stringstream, explicit stringstream (const string& str , ios_base::openmode which = ios_base::in | ios_base::out); , you can find details here
As for your question here is a sample code,
#include <string>
#include <iostream>
#include <sstream>
void Logg(const std::ostringstream& message) {
std::cout<<message.str()<<std::endl;
}
int main()
{
std::string a= "other message";
Logg(std::ostringstream("some message"));
Logg(std::ostringstream(a));
Logg(static_cast<std::ostringstream>(a));
}
Output
some message
other message
other message

Related

C++ default output stream what causes an error?

I have opened a file to write to, and according to some conditions sometimes I want to print output to the screen and sometimes to the file. So I edited my function to be like this:
Cacl(const std::string &str, const ofstream &to=std::cout)
But I'm getting an error, what may cause this?
no viable conversion from 'std::__1::ostream' (aka 'basic_ostream<char>') to 'const std::__1::ofstream' (aka 'const basic_ofstream<char>')
void Calculator::solve(const std::string &command, const ofstream &to=std::cout) {
std::cout is an object of type std::ostream which is a base class of std::ofstream (it's more general than std::ofstream), so you could just do:
void Calculator::solve(const std::string &str, std::ostream &to = std::cout) {
// instead of ofstream ^^^^^^^
and now you can pass an ofstream object to this function as well.
Also, the ostream shouldn't be const otherwise you won't be able to write to it.

How to overload an in-place and a copying string manipulation functions?

I would like to be able to do the following:
std::cout << str_manip("string to manipulate");
as well as
std::string str;
str_manip(str);
std::cout << str;
For this, I have two functions
#include <string>
// copying
std::string str_manip(std::string str)
{
// manipulate str
return str;
}
// in-place
void str_manip(std::string& str)
{
// manipulate str
}
but they produce the following error:
error: call of overloaded 'str_manip(std::__cxx11::string&)' is ambiguous
How can I overcome this?
The problem is with this call:
std::string str;
str_manip(str);
std::cout << str;
The compiler doesn't know which version of str_manip to call.
You can change your functions to look like this:
#include <string>
// copying
std::string str_manip(const std::string& str)
{
std::string dup = str;
// manipulate dup
return dup;
}
// in-place
void str_manip(std::string& str)
{
// manipulate str
}
Now, the compiler knows that the ambiguous call has to be the function that takes the non-const parameter. You can also be sure that your call that returns a std::string to the << operator isn't modifying your string.
This might be not the thing you are looking for, but for your code
std::cout << str_manip("string to manipulate");
the parameter to str_manip is not a string but const char* (actually an array, but convertible to a char pointer). You can overload based on that.
std::string str_manip(const char* s)
{
std::string str(s); // create str
// manipulate str
return str;
}
However, let's look at the big picture. When you see str_manip in your code, does this mean "change the string" or "make a new string based on the given string"? Do you want to be intentionally ambivalent on the real meaning?
Consider yourself reading your code in 1 year in future. What will you think when you see a call to str_manip - does this mutate its parameter? Does the answer to the previous question depend on context?
The goal in writing code is to make it clear, especially in a multi-paradigm language like C++. So, in my opinion, just don't do overloading that you are thinking about. Instead, make 2 distinct names, like
void frobnicate_str(std::string&) {...}
std::string get_frobnicated_str(std::string) {...}

Strange behavior of stringstream passed by reference

For a project, I'd like to use stringstream to carry on data. To achieve this goal, I have to pass some stringstream as parameter to some function, but when I output the stringstreams, I see something like an address.
The code :
#include <iostream>
#include <sstream>
void doStuff(const std::iostream& msg)
{
std::cerr << msg << std::endl;
}
int main(void)
{
doStuff(std::stringstream("av"));
}
The output is :
0xbff4eb40
Can someone explains why I get an address when passing an rvalue ?
And why can't I pass a stringstream by value ?
You probably want to access the string on which the stringstream is storing its data:
void doStuff(const std::stringstream& msg)
{
std::cerr << msg.str() << std::endl;
}
What is happening in your code is that iostreams contain a void* operator which returns 0 if the stream contains any error or has reached EOF, and another value otherwise. This is usefull for error checking.
When you try to write you stream to std::cerr, the compiler realizes that the stream can be converted to a void* using that operator, and that a void* can be written to a ostream(the operator<< has been defined), and therefore uses it.
Note that i changed the method's signature so that it receives an std::stringstream as an argument, since std::iostream::str is not defined(this method is only available on string streams).
You get an address because it (like other streams) has a conversion to void * (which is primarily useful as a Boolean, to see whether reading/writing the stream has failed).
You can't pass it by value, because streams (again, in general, not just stringstreams) don't support copying and/or assigning.
To print the content of the stream, you could do something like:
void dostuff(std::iostream &msg) {
std::cerr << msg.rdbuf() << "\n";
}
Edit: Here's a complete demo program:
#include <iostream>
#include <sstream>
void show(std::ostream &os) {
std::cout << os.rdbuf() << "\n";
}
int main(){
std::stringstream test("whatever");
show(test);
return 0;
}
When I execute it, the output I get is the expected "whatever".

operator<< and std::stringstream reference?

I have a class that holds a reference to a stringstream (used as an overall application log). How do I add text to the referenced stringstream?
An example (as I cannot post actual source here...)
main
stringstream appLog;
RandomClass myClass;
.....
myClass.storeLog(&applog);
myClass.addText("Hello World");
cout << appLog.str().c_str() << endl;
RandomClass cpp
void RandomClass::storeLog(stringstream *appLog)
{
m_refLog = appLog;
}
void RandomClass::addText(const char text[])
{
m_refLog << text; //help here...?
}
I'm getting the following error in my real app using a very similar setup and method structure as above.
error C2296: '<<' : illegal, left operand has type 'std::stringstream *'
error C2297: '<<' : illegal, right operand has type 'const char [11]'
I know the error is because i'm using a reference and still trying to do '<<', but how else am I to do it? m_refLog-><<???
De-reference the pointer first
void RandomClass::addText(const char text[])
{
if ( m_refLog != NULL )
(*m_refLog) << text;
}
In the constructor, initialize the member pointer to stringstream with NULL
RandomClass::RandomClass() : m_refLog(NULL)
{
...
}
It looks like your m_refLog member is a StringStream * (i.e. a pointer-to-StringStream), not a StringStream (or a StringStream &. That is the source of your compile errors.
You have a pointer, not a reference. Dereference it to obtain the stream itself.
(Recall that ptr->foo() is equivalent to (*ptr).foo().)
I'd also recommend that your functions accept const std::string& instead of pointers to C-style char buffers.
And the .c_str() in your example is redundant.
void RandomClass::addText(const std::string& text) {
(*m_refLog) << text;
}

Reading file until blank line

After reading Jerry Coffin's answer on this question I copy-pasted his code into my editor, and after some minor edits it compiled and run like it should.
Here is the code after the changes:
#include <iostream>
#include <string>
#include <istream>
#include <fstream>
class non_blank {
private:
std::string data_;
friend std::istream& operator>> (std::istream &is, non_blank &n) {
std::getline(is, n.data_);
if (n.data_.length() == 0) {
is.setstate(std::ios::failbit);
}
return is;
}
public:
operator std::string() const {
return data_;
}
};
int main(int, char *[]) {
non_blank line;
std::ifstream ifs("teste.txt");
while(ifs >> line) {
//std::cout << line; <----- error
std::string s = line;
std::cout << s << std::endl;
}
return 0;
}
I've got an error when trying to use a non_blank variable in a std::cout <<... expression. Shouldn't I be able to use a variable of the type non_blank anywhere I would use a std::string? Isn't it the purpose of the cast/conversion operator?? answer
Why can't I access the private variable string::data_ directly in the definition of the operator >>?
Here is the error I got:
..\main.cpp: In function `std::istream& operator>>(std::istream&, non_blank&)':
..\main.cpp:21: error: invalid use of non-static data member `non_blank::data_'
..\main.cpp:26: error: from this location
Shouldn't I be able to use a variable
of the type non_blank anywhere I would
use a std::string? Isn't it the
porpuse of the cast operator?
Not quite. If the compiler sees you doing something that it knows requires a std::string, it can call your conversion operator to get one. But in the case of the ostream operator <<, it doesn't have a single specific function to call, but rather quite a lot of them, all different and none matching precisely the actual type you mean to print. So it lists a whole bunch of candidates, none of which is a strong enough match. You need to define an ostream operator << for your type in order to make it print as it should.
As for your operator >>, you should make it not be a member of your class. Declare it as a friend within the class declaration if you must, but write the function itself outside.