Simple C++ that just fails to do what it is supposed to

M

Michael Goldshteyn

Consider the following two lines of code, the first intended to print "Hello
world\n" and the second intended to print the character 'P' to stdout.

---
std::cout << static_cast<std::eek:stringstream &>(std::eek:stringstream() <<
"Hello world\n").str();

std::cout << static_cast<std::eek:stringstream &>(std::eek:stringstream() <<
'P').str();
---

Instead, the first line print the address of the string literal "Hello
world\n" and the second prints the ASCII value of 'P', 80.

I would like a meaningful discussion as to why this is happening. It appears
that in the first case, the const char * that is the string literal is being
interpreted in void * context and in the second case, the character is
somehow being interpreted as an int.

Thanks,

Mike
 
A

Alf P. Steinbach

* Michael Goldshteyn:
Consider the following two lines of code, the first intended to print "Hello
world\n" and the second intended to print the character 'P' to stdout.

---
std::cout << static_cast<std::eek:stringstream &>(std::eek:stringstream() <<
"Hello world\n").str();

std::cout << static_cast<std::eek:stringstream &>(std::eek:stringstream() <<
'P').str();
---

Instead, the first line print the address of the string literal "Hello
world\n" and the second prints the ASCII value of 'P', 80.

I would like a meaningful discussion as to why this is happening. It appears
that in the first case, the const char * that is the string literal is being
interpreted in void * context and in the second case, the character is
somehow being interpreted as an int.

Right. std::eek:stringstream() produces a temporary. It doesn't match a
std::eek:stringstream& parameter, so the only operations available (here)
are the member functions, hence the member operator<<(void*) is used for
the first example, and presumably sometthing like operator<<(int) for
the second -- check it out if the details are of interest.

If you really want to (but you shouldn't want that), call a member that
returns a std::eek:stream reference, before applying << -- again, check
it out if the details are of interest.
 
J

Jack Klein

Consider the following two lines of code, the first intended to print "Hello
world\n" and the second intended to print the character 'P' to stdout.

---
std::cout << static_cast<std::eek:stringstream &>(std::eek:stringstream() <<
"Hello world\n").str();

std::cout << static_cast<std::eek:stringstream &>(std::eek:stringstream() <<
'P').str();
---

Instead, the first line print the address of the string literal "Hello
world\n" and the second prints the ASCII value of 'P', 80.

I would like a meaningful discussion as to why this is happening. It appears

What do you consider to be a meaningful discussion? How about the
fact that the code does exactly what it is supposed to do, according
to the C++ standard, and your expectations are wrong?
that in the first case, the const char * that is the string literal is being
interpreted in void * context and in the second case, the character is
somehow being interpreted as an int.

The insertion operator (<<) for streams is overloaded for all the
built-in types. Its purpose is to generate text streams, so for all
integer and floating point arithmetic types it performs a numeric
value to text conversion and inserts the text into the stream.

Type char is a character type, so this numeric value to text
conversion is performed, exactly as the standard requires it to be. In
your character set, probably ASCII, the numeric value of 'P' is 80.

There is a special overload for pointer to character types. This
overload is based on the assumption that they are pointing to C style
strings (arrays of characters terminated by a '\0' character). Such
strings are already text, so no conversion is necessary, the C string
is merely inserted into the stream as-is.

On the relatively rare occasions when you actually what to output a
text representation of the address contained in a pointer to char,
rather than the C string it is assumed to point to, you merely cast it
to pointer to void, which has no such overload.
 
M

Michael Goldshteyn

Jack Klein said:
What do you consider to be a meaningful discussion? How about the
fact that the code does exactly what it is supposed to do, according
to the C++ standard, and your expectations are wrong?


The insertion operator (<<) for streams is overloaded for all the
built-in types. Its purpose is to generate text streams, so for all
integer and floating point arithmetic types it performs a numeric
value to text conversion and inserts the text into the stream.

Type char is a character type, so this numeric value to text
conversion is performed, exactly as the standard requires it to be. In
your character set, probably ASCII, the numeric value of 'P' is 80.

There is a special overload for pointer to character types. This
overload is based on the assumption that they are pointing to C style
strings (arrays of characters terminated by a '\0' character). Such
strings are already text, so no conversion is necessary, the C string
is merely inserted into the stream as-is.

On the relatively rare occasions when you actually what to output a
text representation of the address contained in a pointer to char,
rather than the C string it is assumed to point to, you merely cast it
to pointer to void, which has no such overload.

Either you misunderstood my argument or I am not understanding your reply. I
was expecting the string and the character to be outputted and got their
address and ASCII value, respectively, instead.

Mike
 
M

Michael Goldshteyn

Alf P. Steinbach said:
* Michael Goldshteyn:

Right. std::eek:stringstream() produces a temporary. It doesn't match a
std::eek:stringstream& parameter, so the only operations available (here) are
the member functions, hence the member operator<<(void*) is used for the
first example, and presumably sometthing like operator<<(int) for the
second -- check it out if the details are of interest.

If you really want to (but you shouldn't want that), call a member that
returns a std::eek:stream reference, before applying << -- again, check it
out if the details are of interest.

I understand your reply. I do not, however, understand the logic of having
overloaded operator<< member functions for void * and int, and not for all
of the other built in types. There should have been no such functions, as
members of the ostringstream class, or all of them should have been included
(i.e. for all of the built-in types), as is the case for non-member
operator<< functions that work with an ostringstream reference.

Mike
 
V

Victor Bazarov

Michael said:
[..] I do not, however, understand the logic of
having overloaded operator<< member functions for void * and int, and
not for all of the other built in types. There should have been no
such functions, as members of the ostringstream class, or all of them
should have been included (i.e. for all of the built-in types), as is
the case for non-member operator<< functions that work with an
ostringstream reference.

That's a very valid concern. Posting it to 'comp.std.c++' can help
clear it up. Ask for *rationale* behind that decision. We here mostly
discuss "how", very rarely "why". They there have the "why" answers.

V
 

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

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top