Why this code can't compile?

D

David Lee

Hi, all
I got the following code from
http://builder.com.com/5100-6370_14-5079969.html,
but it can't compile, neither can I figure out how to fix it. Anyone
pls give me an
explanation?

1 #include <string>
2 #include <sstream>
3 #include <iostream>
4
5 class str_stream
6 {
7 public:
8 std::stringstream & underlying_stream() const
9 { return m_streamOut; }
10
11 operator std::string() const
12 {
13 return m_streamOut.str();
14 }
15
16 private:
17 mutable std::stringstream m_streamOut;
18 };
19
20 template<class T>
21 const str_stream & operator<< (const str_stream & out, const T
& value)
22 {
23 out.underlying_stream() << value;
24 return out;
25 }
26
27 int main()
28 {
29 int num = 48;
30 std::string str;
31
32 // str_stream s;
33 // str = s << "We have " << num << " words";
34 str = str_stream() << "We have " << num << " words";
35
36 std::cout << str << std::endl;
37
38 return 0;
39 }
40

I changed the code by omitting line 34 (which is the original version
at that site) and adding
line 32 and 33. It can work correctly. Since that I haven't been
programming with C++ for
rather a long time, I need your help thirstily.

Thanks in advance.
 
V

Victor Bazarov

David said:
I got the following code from
http://builder.com.com/5100-6370_14-5079969.html,
but it can't compile, neither can I figure out how to fix it. Anyone
pls give me an
explanation?

1 #include <string>

Please do not include line numbers like this. They prevent us from
simply copying the code from the message into a text editor and
compiling it. If you needed to refer to any line by its number, just
add a comment to that line indicating what its number is.
2 #include <sstream>
3 #include <iostream>
4
5 class str_stream
6 {
7 public:
8 std::stringstream & underlying_stream() const
9 { return m_streamOut; }
10
11 operator std::string() const
12 {
13 return m_streamOut.str();
14 }
15
16 private:
17 mutable std::stringstream m_streamOut;
18 };
19
20 template<class T>
21 const str_stream & operator<< (const str_stream & out, const T
& value)
22 {
23 out.underlying_stream() << value;
24 return out;
25 }
26
27 int main()
28 {
29 int num = 48;
30 std::string str;
31
32 // str_stream s;
33 // str = s << "We have " << num << " words";
34 str = str_stream() << "We have " << num << " words";
35
36 std::cout << str << std::endl;
37
38 return 0;
39 }
40

I changed the code by omitting line 34 (which is the original version
at that site) and adding
line 32 and 33. It can work correctly. Since that I haven't been
programming with C++ for
rather a long time, I need your help thirstily.

I ran your program as is (after stripping all those line numbers)
and it compiled and ran and output "We have 48 words<newline>".
Is that what you expected? I guess I am not sure what your problem
is. The code is fine.

V
 
D

David Lee

Hi, Victor Bazarov
Sorry for the inconvenience with line numbers attached.

Yes I want that output. I'm working on Fedora Core 4 with g++ 4.0.0,
and the compiler compliant that:

string.cc: In copy constructor ‘std::basic_ios<char,
std::char_traits<char> >::basic_ios(const std::basic_ios<char,
std::char_traits<char> >&)’:
/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../../include/c++/4.0.0/bits/ios_base.h:779:
error: ‘std::ios_base::ios_base(const std::ios_base&)’ is
private
string.cc:34: error: within this context
string.cc: In copy constructor ‘std::basic_stringbuf<char,
std::allocator<char> >::basic_stringbuf(const said:
&)’:
/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../../include/c++/4.0.0/streambuf:772:
error: ‘std::basic_streambuf<_CharT,
_Traits>::basic_streambuf(const std::basic_streambuf<_CharT, _Traits>&)
[with _CharT = char, _Traits = std::char_traits<char>]’ is
private
string.cc:34: error: within this context
 
V

Victor Bazarov

David said:
Hi, Victor Bazarov
Sorry for the inconvenience with line numbers attached.

No biggie. Just don't make a habit out of it :*)
Yes I want that output. I'm working on Fedora Core 4 with g++ 4.0.0,
and the compiler compliant that:

string.cc: In copy constructor â?~std::basic_ios<char,
std::char_traits<char> >::basic_ios(const std::basic_ios<char,
std::char_traits<char> >&)â?T:
/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../../include/c++/4.0.0/bits/ios_base.h:779:
error: â?~std::ios_base::ios_base(const std::ios_base&)â?T is
private
string.cc:34: error: within this context
string.cc: In copy constructor â?~std::basic_stringbuf<char,
std::char_traits<char>, std::allocator<char> >::basic_stringbuf(const
std::basic_stringbuf said:
/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../../include/c++/4.0.0/streambuf:772:
error: â?~std::basic_streambuf<_CharT,
_Traits>::basic_streambuf(const std::basic_streambuf<_CharT,
_Traits>&)
[with _CharT = char, _Traits = std::char_traits<char>]â?T is
private
string.cc:34: error: within this context

Well, I don't know what to tell you. Both VC++ v8 and Comeau C++ (online)
compile the code without a complaint. Try 'gnu.g++.help' or GNU online
forums. Perhaps there is a bug in 4.0 or in the library that ships with it.

V
 
K

Kai-Uwe Bux

David said:
Hi, all
I got the following code from
http://builder.com.com/5100-6370_14-5079969.html,
but it can't compile, neither can I figure out how to fix it. Anyone
pls give me an
explanation?

1 #include <string>
2 #include <sstream>
3 #include <iostream>
4
5 class str_stream
6 {
7 public:
8 std::stringstream & underlying_stream() const
9 { return m_streamOut; }
10
11 operator std::string() const
12 {
13 return m_streamOut.str();
14 }
15
16 private:
17 mutable std::stringstream m_streamOut;
18 };
19
20 template<class T>
21 const str_stream & operator<< (const str_stream & out, const T
& value)
22 {
23 out.underlying_stream() << value;
24 return out;
25 }
26
27 int main()
28 {
29 int num = 48;
30 std::string str;
31
32 // str_stream s;
33 // str = s << "We have " << num << " words";
34 str = str_stream() << "We have " << num << " words";

In this line, you bind the temporary str_stream() to the non-const reference
parameter of operator<<( str_stream &, T const & ). This does not fly
because the standard forbids that.

35
36 std::cout << str << std::endl;
37
38 return 0;
39 }
40


Here is a fix:

#include <string>
#include <sstream>
#include <iostream>

class str_stream
{
public:

std::stringstream & underlying_stream() const
{ return m_streamOut; }

operator std::string() const
{
return m_streamOut.str();
}

str_stream & me ( void ) {
return ( *this );
}


private:
mutable std::stringstream m_streamOut;
};

template<class T>
const str_stream & operator<< (const str_stream & out, const T & value)
{
out.underlying_stream() << value;
return out;
}

int main() {
int num = 48;
std::string str;

str = str_stream().me() << "We have " << num << " words";

std::cout << str << std::endl;

return 0;
}


This compiles because it is legal to call a non-const member function of a
temporary object. The return value of me() is a reference, which can be
bound to the first parameter of operator<<(). That the reference just so
happens to refer to a temporary is immaterial.


Best

Kai-Uwe Bux
 
K

Kai-Uwe Bux

Kai-Uwe Bux said:
In this line, you bind the temporary str_stream() to the non-const
reference parameter of operator<<( str_stream &, T const & ). This does
not fly because the standard forbids that.

Oops, sorry: I missed the const in operator<<(). BTW: that const is ill
advises logic and only serves to make the compiler shut up. The operation
is non-const!

[snip]


Best

Kai-Uwe Bux
 
K

Kai-Uwe Bux

David said:
Hi, all
I got the following code from
http://builder.com.com/5100-6370_14-5079969.html,
but it can't compile, neither can I figure out how to fix it. Anyone
pls give me an
explanation?

1 #include <string>
2 #include <sstream>
3 #include <iostream>
4
5 class str_stream
6 {
7 public:
8 std::stringstream & underlying_stream() const
9 { return m_streamOut; }
10
11 operator std::string() const
12 {
13 return m_streamOut.str();
14 }
15
16 private:
17 mutable std::stringstream m_streamOut;
18 };
19
20 template<class T>
21 const str_stream & operator<< (const str_stream & out, const T
& value)
22 {
23 out.underlying_stream() << value;
24 return out;
25 }
26
27 int main()
28 {
29 int num = 48;
30 std::string str;
31
32 // str_stream s;
33 // str = s << "We have " << num << " words";
34 str = str_stream() << "We have " << num << " words";
35
36 std::cout << str << std::endl;
37
38 return 0;
39 }
40

I think I understand now what is going on. I stripped all of the example
down to:

#include <sstream>

struct str_stream {
mutable std::stringstream m_streamOut;
};

void dump ( str_stream const & out, int value ) {
out.m_streamOut << value;
}

int main() {
dump( str_stream(), 2 );
}


What happens is that according to clause [8.5.3/5] and implementation is
free to choose the mechanism by which to initialize const references from
things that are not lvalues. It may choose to

(a) directly bind to an rvalue, or
(b) copy construct a new temporary from the passed object and bind that.

Your implementation seems to opt for (b) which implies that you need a copy
constructor. However, stringstreams do not have those and you get a load of
error messages.

Now, what I do not understand is why this compiles on Comeau. The standard
mandates that the copy constructor be callable in any case. So, maybe my
analysis is mistaken.


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,076
Latest member
OrderKetoBeez

Latest Threads

Top