 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Paolo Carlini Guest
|
Posted: Sat Aug 21, 2004 4:07 pm Post subject: Why operator<<(bool) for volatile char* ?? |
|
|
Hi,
anyone is willing to explain why this snippet
volatile char str[] = "a";
std::cout << str;
prints "1"? Or, in other terms, why operator<<(bool) is
the best match?
Thanks in advance,
Paolo.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Sun Aug 22, 2004 10:58 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
Paolo Carlini wrote:
| Quote: | anyone is willing to explain why this snippet
volatile char str[] = "a";
std::cout << str;
prints "1"? Or, in other terms, why operator<<(bool) is
the best match?
|
When passed to a function, 'str' decays to a 'char volatile*'. Looking at
all overloads of 'operator<<', there is none matching it. 'void const*' or
'char const*' come close, but only that. Therefore, the best way it to
evaluate the pointer as a boolean expression, i.e. 'str!=0' and that
yields 'true' or '1'.
In case you wonder why 'char const*' does not fit, the reason is that
'volatile' (in that context) works just like 'const': it can be added but
not removed implicitly. To remove the 'volatile' qualifier, you need a
'const_cast'.
Uli
--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daryle Walker Guest
|
Posted: Sun Aug 22, 2004 11:07 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
In article <2oomqsFcil47U1 (AT) uni-berlin (DOT) de>,
Paolo Carlini <pcarlini (AT) suse (DOT) de> wrote:
| Quote: | anyone is willing to explain why this snippet
volatile char str[] = "a";
std::cout << str;
prints "1"? Or, in other terms, why operator<<(bool) is
the best match?
|
I think the "volatile" is screwing you up.
First, since there are (almost) no array operations, "str" devolves to a
pointer. So we want the closest match to one of:
1. std::ostream & std::ostream::operator << ( char volatile * );
2. std::ostream & operator <<( std::ostream &, char volatile * );
([1] is a member function, [2] is a free function.)
We have these member/free functions:
3. std::ostream & std::ostream::operator << ( void const * );
4. std::ostream & operator <<( std::ostream &, char const * );
What you're missing is that:
"T *" -> "T const *" is implicit
"T *" -> "T volatile *" is also implicit
But
"T volatile *" -> "T const *" can't be done implicitly! An explicit
const_cast is needed, so [3] and [4] are _not_ considered.
This means that the "bool" conversion is the only valid one. (We
wouldn't have this problem if the pointer inserters used "char|void
const volatile *" instead.)
This problem will get worse if we add C-1999's "restrict".
--
Daryle Walker
Mac, Internet, and Video Game Junkie
dwalker07 AT snet DOT net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Paolo Carlini Guest
|
Posted: Mon Aug 23, 2004 10:24 am Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
Thanks for your reply,
Ulrich Eckhardt wrote:
| Quote: | Therefore, the best way it to
evaluate the pointer as a boolean expression, i.e. 'str!=0' and that
yields 'true' or '1'.
|
But why the pointer *must* be evaluated as a boolean? Why not as a short
or an integer or another of the types in 27.6.2.5.2? Really, my question
is this one...
Thanks,
Paolo.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
llewelly Guest
|
Posted: Mon Aug 23, 2004 10:26 am Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
Paolo Carlini <pcarlini (AT) suse (DOT) de> writes:
| Quote: | Hi,
anyone is willing to explain why this snippet
volatile char str[] = "a";
std::cout << str;
prints "1"? Or, in other terms, why operator<<(bool) is
the best match?
|
There is no implicit conversion from 'char volatile*' to 'char const*'
. So operator<<(char const*) isn't a match. There is no
operator<<(char volatile*) or operator<<(char volatile const*) .
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Paolo Carlini Guest
|
Posted: Mon Aug 23, 2004 10:27 am Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
Paolo Carlini wrote:
| Quote: | But why the pointer *must* be evaluated as a boolean? Why not as a short
or an integer or another of the types in 27.6.2.5.2? Really, my question
is this one...
|
Ok, now I know the answer: roughly, missing a perfect match, a match with
minor adjustments and a match with promotion, a match with standard
conversions is looked for: there is a standard conversion from pointer to
bool, *not* to other integral types.
This explanation I found in Vendevoorde/Josuttis appendix B and the standard
section 4.
Thanks again to everyone,
Paolo.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Tue Aug 24, 2004 10:51 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
Paolo Carlini <carlinip (AT) tiscali (DOT) it> wrote
[Asks why
volatile char*str="x";
cout << str;
shows 1 -- it's converting to bool instead of char*]
| Quote: | Ok, now I know the answer: roughly, missing a perfect match, a match with
minor adjustments and a match with promotion, a match with standard
conversions is looked for: there is a standard conversion from pointer to
bool, *not* to other integral types.
This explanation I found in Vendevoorde/Josuttis appendix B and the standard
section 4.
|
I believe that the rationale goes back to classic C, before there was a
bool type. It was (still is, I suspect) common for code to do this:
const char*name = getname();
if (name) {
// Name was not null, so use it
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Wed Aug 25, 2004 8:56 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
Paolo Carlini <pcarlini (AT) suse (DOT) de> wrote
| Quote: |
anyone is willing to explain why this snippet
volatile char str[] = "a";
std::cout << str;
prints "1"? Or, in other terms, why operator<<(bool) is
the best match?
|
More type conversions seems to be involved.
volatile char* str -> volatile bool str -> bool str -> int str
Is this path legal according to the Standard?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Aug 27, 2004 2:45 am Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
[email]hosoda (AT) jtec (DOT) or.jp[/email] (Tokyo Tomy) wrote in message
news:<49c1da0b.0408242316.56490c9e (AT) posting (DOT) google.com>...
| Quote: | Paolo Carlini <pcarlini (AT) suse (DOT) de> wrote in message
news:<2oomqsFcil47U1 (AT) uni-berlin (DOT) de>...
anyone is willing to explain why this snippet
volatile char str[] = "a";
std::cout << str;
prints "1"? Or, in other terms, why operator<<(bool) is the best
match?
More type conversions seems to be involved.
volatile char* str -> volatile bool str -> bool str -> int str
Is this path legal according to the Standard?
|
The path is "volatile char[2]" -> "volatile char*" -> bool. The result
of a conversion is an rvalue, and rvalues of non-class type (like bool)
don't have const-volatile qualifiers.
The standard says that by default, bool is output as if it were an
integer. In fact, although there is a boolalpha flag described in table
83 of §27.4.2.1.2, and the numpunct facet contains the functions
truename() and falsename(), §27.6.2.5.2 (formatted output for arithmetic
types, explicitly including bool) just refers to §22.2.2.2, the num_put
facet, and I can't find anything there which says that the boolalpha
flag is actually tested, or that truename() or falsename() may be used.
So unless I've missed something, you have to specialize the num_put
facet yourself and imbue a new locale to get anything but a numeric
value for a bool. (But I'm almost sure that this is an oversight, and
that I've missed something somewhere.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Fri Aug 27, 2004 1:03 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote in message news:<d6652001.0408260005.4de7d3d2 (AT) posting (DOT) google.com>...
| Quote: | hosoda (AT) jtec (DOT) or.jp (Tokyo Tomy) wrote in message
news:<49c1da0b.0408242316.56490c9e (AT) posting (DOT) google.com>...
Paolo Carlini <pcarlini (AT) suse (DOT) de> wrote in message
news:<2oomqsFcil47U1 (AT) uni-berlin (DOT) de>...
anyone is willing to explain why this snippet
volatile char str[] = "a";
std::cout << str;
prints "1"? Or, in other terms, why operator<<(bool) is the best
match?
More type conversions seems to be involved.
volatile char* str -> volatile bool str -> bool str -> int str
Is this path legal according to the Standard?
The path is "volatile char[2]" -> "volatile char*" -> bool. The result
of a conversion is an rvalue, and rvalues of non-class type (like bool)
don't have const-volatile qualifiers.
...
|
James Kanze, thank you for your kind explanation. I did not think my
guesswork above was correct. However, I still do not understand why
the code below fail to compile with my MSVC++6. Would somebody kindly
explain the reason?
#include <iostream>
using namespace std;
void f(int n ) { cout << n << endl; }
void f(char* str) { cout << str << endl; }
void f(const char* str) { cout << str << endl; }
void f(const char c) { cout << c << endl; }
int main( )
{
volatile char str[] = "a";
cout << str << endl;
f(str); // error
return 0;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Tue Aug 31, 2004 12:04 am Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
[email]hosoda (AT) jtec (DOT) or.jp[/email] (Tokyo Tomy) wrote in message
news:<49c1da0b.0408262321.4b824d74 (AT) posting (DOT) google.com>...
| Quote: | However, I still do not understand why
the code below fail to compile with my MSVC++6. Would somebody kindly
explain the reason?
#include
using namespace std;
void f(int n ) { cout << n << endl; }
void f(char* str) { cout << str << endl; }
void f(const char* str) { cout << str << endl; }
void f(const char c) { cout << c << endl; }
int main( )
{
=09volatile char str[] = "a";
=09cout << str << endl;
=09f(str); // error
=09return 0;
}
|
Why should it compile? When passed to a function, an array degenerates
into a pointer to the first element. In this case, thus, you have a
char volatile*. An implicit conversion is not allowed to remove the
volatile, so none of the f's taking a pointer can be called. And a
pointer cannot convert implicitly to an arbitrary integral type, so none
of the f's taking an integral type (char, int) can be called.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Old Wolf Guest
|
Posted: Tue Aug 31, 2004 12:10 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
Daryle Walker <dwalker07 (AT) snet (DOT) net> wrote:
| Quote: |
What you're missing is that:
"T *" -> "T const *" is implicit
"T *" -> "T volatile *" is also implicit
But
"T volatile *" -> "T const *" can't be done implicitly! An explicit
const_cast is needed, so [3] and [4] are _not_ considered.
This means that the "bool" conversion is the only valid one. (We
wouldn't have this problem if the pointer inserters used "char|void
const volatile *" instead.)
|
I think this is a good thing. If a function expects a T const *,
and you pass it a T volatile *, you would get UB (presumably) if
the pointed-to item changed during the function's processing.
Why should the standard library bloat its code to support volatile
objects? The onus is on either:
a) the implementor of T, to provide a method that creates a
non-volatile T based on a volatile one, or
b) you, to do a const_cast<> when you know it is safe.
| Quote: | This problem will get worse if we add C-1999's "restrict".
|
Not really, all the standard library functions put 'restrict'
everywhere, so I don't see where there would be a problem.
As with const and volatile, you can implicitly convert a
non-restrict to a restrict.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Tue Aug 31, 2004 7:29 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote in message news:<d6652001.0408300108.54bc8ad (AT) posting (DOT) google.com>...
| Quote: | hosoda (AT) jtec (DOT) or.jp (Tokyo Tomy) wrote in message
news:<49c1da0b.0408262321.4b824d74 (AT) posting (DOT) google.com>...
However, I still do not understand why
the code below fail to compile with my MSVC++6. Would somebody kindly
explain the reason?
...
Why should it compile? When passed to a function, an array degenerates
into a pointer to the first element. In this case, thus, you have a
char volatile*. An implicit conversion is not allowed to remove the
volatile, so none of the f's taking a pointer can be called. And a
pointer cannot convert implicitly to an arbitrary integral type, so none
of the f's taking an integral type (char, int) can be called.
|
James Kanze, thank you for your reply. Please excuse me for my
ignorance on C++, and let me ask you or others more.
Q1. James Kaze said
| Quote: | An implicit conversion is not allowed to remove the
volatile,
but if I add "void f(bool b)" to the previous code as shown below, the |
code successfully complies with my MSVC++6 and the volatile seems to
be removed.
Q2. Is there any deference in looking-up methods between, std::ostream
& std::ostream::operator << ( char const * ) etc and f(char const* )
etc. In other words, if I provide f functions with all the same
combinations of arguments as std::ostream::operator << has or free
function std::ostream & operator << has, can f functions accept
volatile char* str or not? If not, would you kindly tell me how the
looling-up methods are deferent?
#include
using namespace std;
void f(int n ) { cout << n << endl; }
void f(char* str) { cout << str << endl; }
void f(const char* str) { cout << str << endl; }
void f(char c) { cout << c << endl; }
void f(bool b) { cout << b << endl; } // newly added
int main()
{
volatile char str[] = "a";
cout << str << endl;
f(str); // ok
return 0;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Sep 01, 2004 8:58 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
[email]hosoda (AT) jtec (DOT) or.jp[/email] (Tokyo Tomy) wrote in message
news:<49c1da0b.0408302323.65d70285 (AT) posting (DOT) google.com>...
| Quote: | kanze (AT) gabi-soft (DOT) fr wrote in message
news:<d6652001.0408300108.54bc8ad (AT) posting (DOT) google.com>...
[email]hosoda (AT) jtec (DOT) or.jp[/email] (Tokyo Tomy) wrote in message
news:<49c1da0b.0408262321.4b824d74 (AT) posting (DOT) google.com>...
However, I still do not understand
why the code below fail to compile with my MSVC++6. Would somebody
kindly explain the reason?
...
Why should it compile? When passed to a function, an array
degenerates into a pointer to the first element. In this case,
thus, you have a char volatile*. An implicit conversion is not
allowed to remove the volatile, so none of the f's taking a pointer
can be called. And a pointer cannot convert implicitly to an
arbitrary integral type, so none of the f's taking an integral type
(char, int) can be called.
Q1. James Kaze said
An implicit conversion is not allowed to remove the
volatile,
but if I add "void f(bool b)" to the previous code as shown below, the
code successfully complies with my MSVC++6 and the volatile seems to
be removed.
|
I should have benn more precise. When I said that an implicit
conversion is not allowed to remove volatile or const. An implicit
conversion of a pointer or a reference is not allowed to remove the
volatile or the const of what is pointed to or referenced. When you
convert a pointer to bool, the situation is somewhat different -- after
the conversion, there is nothing that is pointed to. Basically, there
are a certain number of implicit conversions T* to U*, but they are very
limited; in particular, U may have more const-volatile qualifiers than
T, but not less. If T and U are themselves pointers, the rules get even
more complicated, but the overall rule is to preserve the semantics of
const and volatile -- if the conversion could, in some way, allow you to
end up accessing something which was declared const or volatile through
an expression which doesn't consider it const or volatile, the
conversion cannot be implicit. In the case of T* to bool, the rule is
that the implicit conversion is legal regardless of what T is. Thus, it
can take place if T is char, but also if T is const char or volatile
char.
| Quote: | Q2. Is there any deference in looking-up methods between, std::ostream
& std::ostream::operator << ( char const * ) etc and f(char const* )
etc. In other words, if I provide f functions with all the same
combinations of arguments as std::ostream::operator << has or free
function std::ostream & operator << has, can f functions accept
volatile char* str or not? If not, would you kindly tell me how the
looling-up methods are deferent?
|
No. The look-up rules are basically identical. (There are some
differences in the way function overload resolution works in the case of
a named function and in the case of an operator, but they don't concern
us here.) If you provide the same name function overloads, the compiler
should do the same overload resolution, with the same results.
If you provide functions f( char* ) and f( char const* ), you cannot
call either of them with a volatile char*, and they will not be
considered in overload resolution.
| Quote: | #include
using namespace std;
void f(int n ) { cout << n << endl; }
void f(char* str) { cout << str << endl; }
void f(const char* str) { cout << str << endl; }
void f(char c) { cout << c << endl; }
void f(bool b) { cout << b << endl; } // newly added
int main()
{
volatile char str[] = "a";
cout << str << endl;
f(str); // ok
|
Yes. I will call f(bool).
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Thu Sep 02, 2004 12:10 pm Post subject: Re: Why operator<<(bool) for volatile char* ?? |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote in message news:<d6652001.0409010105.18e2c3e0 (AT) posting (DOT) google.com>...
| Quote: |
Q2. Is there any deference in looking-up methods between, std::ostream
& std::ostream::operator << ( char const * ) etc and f(char const* )
etc. In other words, if I provide f functions with all the same
combinations of arguments as std::ostream::operator << has or free
function std::ostream & operator << has, can f functions accept
volatile char* str or not? If not, would you kindly tell me how the
looling-up methods are deferent?
No. The look-up rules are basically identical. (There are some
differences in the way function overload resolution works in the case of
a named function and in the case of an operator, but they don't concern
us here.) If you provide the same name function overloads, the compiler
should do the same overload resolution, with the same results.
If you provide functions f( char* ) and f( char const* ), you cannot
call either of them with a volatile char*, and they will not be
considered in overload resolution.
|
Thank you for your reply, Kanze. As I am not a paranoia, let this
question be my last one in this thread and let me express my
appreciation in advance.
In the code below, I am not yet sure why the line (1) works and the
line (2) does not work. The line (1) works on the ostream::operator
<<, while the line (2) works on the f functions which have the all
overloadings as the the ostream::operator << provides, except for the
three overloadings commented out in the below code.
If the same looking-up rules are applied for the both the operator <<
and function f, I think the line (2) should work as the line (1) do.
Maybe, I have missed something in my argument.
#include
void f( char ch ){};
void f( unsigned char uch ){};
void f( signed char sch ){};
void f( const char* psz ){};
void f( const unsigned char *pusz ){};
void f( const signed char *pssz ){};
void f( short s ){};
void f( unsigned short us ){};
void f( int n ){};
void f( unsigned int un ){};
void f( long l ){};
void f( unsigned long ul ){};
void f( float f ){};
void f( double d ){};
void f( long double ld ){};
void f( const void* pv ){};
//ostream& operator <<( streambuf* psb );
//ostream& operator <<( ostream& (*fcn)(ostream&) );
//ostream& operator <<( ios& (*fcn)(ios&) );
int main()
{
volatile char str[] = "a";
std::cout << str; // (1) ok
f(str); // (2) error
return 0;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|