Use of ostringstream inside a function.

I am trying to use a function to display (write or log or display) data for debugging my programs. The idea is to have a possibilty to send a message to 1 or more destinies without to do changes in the program.
I've got a simple solution, but i would like to make it simpler.

I'm sending a reduced version of my code.
Basically, i'm asking you help for solve the syntax error in line 25 (if we remove the slashes in line 25).

I appreciate your help.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Logging / recording messages to different destinations
   # include    <sstream>       // ios; is
   # include    <iostream>	    // cin, cout
using namespace std;

void   dsplCln (int dstny, ostringstream &bufi ) {	// call by reference
	if (dstny == 2 ) cout    << bufi.str() <<endl;
//  if (dstny==3) file3<<bufi.str();  if(dstny>=2) file2<<buf...  
	bufi.str(""); bufi.clear();				// cleans the buffer
}	

   int main(){
   	ostringstream  buff_Os (ostringstream::ate); 
  	string  buff_str, hlpDta=" this.";
  	int 	iVal=345, dstny=3;

// ( 1 ) adding (complex) info to ostringstream
	buff_Os << "Previous " << iVal + 111;
	// after calculations
	buff_Os << hlpDta <<endl;
// ( 2 ) displaying the ostringstream using the function
	dsplCln(2,buff_Os);

//  ( 3 ) i'd like to use (something like) the next sentence instead of ( 1 ) and then ( 2 ):	
//	dsplCln (2, buff_Os << "Previous " << iVal + 111 << hlpDta <<endl );

	return 0;
} 
Last edited on
What does the compiler say in the error message?

For example:
error: invalid initialization of reference of type
  'std::ostringstream& {aka std::basic_ostringstream<char>&}'
  from expression of type
  'std::basic_ostream<char>::__ostream_type {aka std::basic_ostream<char>}'
note: in passing argument 2 of 'void dsplCln(int, std::ostringstream&)'

The return type of operator<< is ostream&, not ostringstream&.
Maybe you want something like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <fstream>
using namespace std;

ostream* Output[4] {
    &cout,
    &cerr,
    nullptr,
    nullptr
};

template<typename... Args>
void display(int dest, Args... args) {
   (*Output[dest] << ... << args) << '\n';
}

int main() {
    ofstream log("log.txt");
    Output[2] = &log;

    int a = 123, b = 3;
    display(0, "speed: ", a * b, " mph");
    display(2, "speed: ", a * b, " mph");
}


Or if you want to be able to send the same message to multiple streams with one command, you could use bit flags, something like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <fstream>
using namespace std;

ostream* Output[4] {
    &cout,
    &cerr,
    nullptr,
    nullptr
};

template<typename... Args>
void display2(int dest, Args... args) {
   (*Output[dest] << ... << args) << '\n';
}

template<typename... Args>
void display(unsigned dests, Args... args) {
    for (int index = 0; dests; ++index, dests >>= 1) {
        if (dests & 1)
            display2(index, forward<Args>(args)...);
    }
}

int main() {
    ofstream log("log.txt");
    Output[2] = &log;

    int a = 123, b = 3;
    display(1|2|4, "speed: ", a * b, " mph");
}

-deleted-
Last edited on
EDIT: Actually, a better solution is to define an operator<< like this:
1
2
3
4
5
template<typename T>
inline ostringstream& operator<<(ostringstream& oss, T const& val) 
{
    return static_cast<ostringstream&>(static_cast<ostream&>(oss) << val); 
}


No need for an explicit out() function.
Last edited on
That works pretty nicely. The casts are interesting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <sstream>
using namespace std;

using Oss = std::ostringstream;

template<typename T>
inline Oss& operator<<(Oss& oss, const T& val)  {
    return (Oss&)((ostream&)oss << val);
}

void f(Oss& oss) {
    cout << oss.str() << '\n';
}

int main() {
    Oss oss;
    f(oss << "val: " << 123);
}

Sorry for the delay¡

keskiverto:
---------------------------------
Yes the error is like the one you showed.
I don't know how to make the convertion

let me try to explain:
// ( 1 ) adding (complex) info to ostringstream
buff_Os << "Previous " << iVal + 111; // normal assignation of data to a stream.

// ( 2 ) displaying the ostringstream using the function
dsplCln(2,buff_Os); // i can call the dspCln routine, with buff_Os without problem.

dsplCln (2, buff_Os << "Previous " << iVal + 111 << hlpDta <<endl );
/* if i remove the slashes from line 25, the compilador detect an error (the same you mencioned.

I was trying to do (on fly) both operations (1) - "load data" and (2) "send the buffer (ostringstream buff_Os) to 1 or 2, or ... "destination(s)" (please see line 8). The routine dspCln sends the message according with the value of the parameter dstny.
---------------------------------

dutch (1st reply):
Sound like the 2nd option. I really need to try the solution you give me.
---------------------------------

TheToaster.
I'm going to try the solution. Looks like fine!
---------------------------------

dutch (2nd reply):
---------------------------------

I think the work is almost done!!!.


Guys tomorrow i'll implement this solution.
Thanks a lot!




I made the following amendmend:

instead of
using Oss = std::ostringstream;
I put
typedef ostringstream Oss;

due to the error (in compilation)
5:7 [Error] expected nested-name-specifier before 'Oss'
Last edited on
Topic archived. No new replies allowed.