 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Torstein Hansen Guest
|
Posted: Wed Feb 18, 2004 12:29 pm Post subject: Compiler error or? Microsoft VC++ v6.0 |
|
|
The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
<code>
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
b.foobar(u0);
b.foobar(u1);
}
</code>
Torstein Hansen
(Remove "RemoveThis" to answer by mail)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ben Hutchings Guest
|
Posted: Thu Feb 19, 2004 10:25 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
Torstein Hansen wrote:
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
snip |
It's a bizarre result of the definition of integer constant
expression. const variables of integer type are integer constant
expressions. Any integer constant expression that evaluates to 0 can
be implicitly converted to a pointer type, resulting in a null pointer
of that type. So u0 is converted to foo((char *)0) but u1 cannot
be converted to foo.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Thu Feb 19, 2004 10:29 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
Torstein Hansen schrieb:
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
|
These 2 constructors can both act as conversion functions.
This will play a role later.
Maybe they should better be declared 'explicit' ?
| Quote: | };
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
|
Invalid C++. You have to return an int.
| Quote: |
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
b.foobar(u0);
|
This call works because
-) u0 is declared as a *constant* with the value zero
-) there is an implicit conversion from the zero constant to a pointer value
-) one of the foo constructors takes a pointer value as argument and is not
'explicit'. (e.g. it can act as conversion function).
The compiler calls the
foo(char*);
constructor of foo, and passes in the null pointer.
You could make the code fail by doing one of this:
-) remove the const from u0.
-) declare the foo(char*) constructor as 'explicit'.
This code cannot work, because there is no implicit conversion from the
constant '1' to a pointer value, so this line triggers a compilation error.
All unsigned long constants except '0' share the same fate.
regards,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Benjamin Golinvaux Guest
|
Posted: Thu Feb 19, 2004 10:34 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
hi
section C.6.2.3 of "the C++ programming language" says
"A constant expression that evaluates to 0 can be implicitly converted
to any pointer or pointer to member type".
This is why
somePointer = NULL
with
#define NULL 0
doesn't require a cast
very handy...
Benjamin-
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
b.foobar(u0);
b.foobar(u1);
}
/code
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Thu Feb 19, 2004 1:31 pm Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
In message <oZuYb.460$72.179822080 (AT) news (DOT) telia.no>, Torstein Hansen
<torsteinRemoveThis (AT) hansen (DOT) as> writes
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
True, with the solitary exception of a compile time zero value which can |
be a null pointer constant. And that is your problem here.
| Quote: |
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
|
This constructs a foo given a pointer to a char. 0 is such a pointer if
it can be interpreted as a null pointer constant. All other integer
values require a cast to convert them (in an implementation defined way)
into a pointer.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Thu Feb 19, 2004 1:36 pm Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without
warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical
value
is used.
|
An intergral constant expression rvalue that evaluates to zero can be
converted to any pointer type. (4.10)
Therefore you can write
char* c = 701 * 1429 - 1001729;
but not
char* c = 661 * 1381- 912840;
Jonathan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Chris Underwood Guest
|
Posted: Thu Feb 19, 2004 2:10 pm Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
I'm just guessing here, but for some reason 0 is a valid pointer
value, but other integers are not.
int main(){
char *a = 0; // This works
int *x = 0; // This works
char *b = 1; // cannot convert blah blah
int *y = 1; // cannot convert blah blah
return 0;
}
Looking a bit further I found
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
In several headers which kind of hints that 0 has an acceptable
conversion to pointers if __cplusplus is defined.
So I'm guessing that 0 converts to a char * which is a default
constructor for foo, so it is constructed and passed to foobar.
To my knowlegde this is not standard C++ behavior, so it is probably a
convient feature for VC++ 6. I hope that helps.
Whats funny is... char *p = (const unsigned long)0; won't work.
hehe...
Chris Underwood
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
b.foobar(u0);
b.foobar(u1);
}
/code
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
bert hubert Guest
|
Posted: Thu Feb 19, 2004 6:18 pm Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
On 2004-02-18, Torstein Hansen <torsteinRemoveThis (AT) hansen (DOT) as> wrote:
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
|
I'm no language lawyer, but expecting an unsigned long to be silently cast
into a char* is wrong. They do that in C :-)
For 0, some special rules might apply (not aware of any, but 0 is somewhat
special), but don't count on it. Whatever the language says, you are in
scary territory here. Don't do it.
--
http://www.PowerDNS.com/ Open Source Database Driven Nameserver
http://lartc.org Linux Advanced Routing & Traffic Control HOWTO
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Steve Dewhurst Guest
|
Posted: Thu Feb 19, 2004 6:22 pm Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
|
An initialized constant integral object is a constant-expression (what
used to be known as an "integer constant expression"). A
constant-expression with a value of 0 may be converted to a null
pointer value. A constant-expression with a value of 1 may not. As
an experiment, try removing the "const" on the declaration of u0 and
see what happens.
Steve
Steve Dewhurst
www.semantics.org
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
PeteK Guest
|
Posted: Fri Feb 20, 2004 12:49 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
b.foobar(u0);
b.foobar(u1);
}
/code
|
OK, It's 1am and I've just got in from the pub,
but I'd say u0 is zero is NULL is a valid char * which converts to a
foo. u1 is a non-zero, which doesn't.
PeteK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Sun Guest
|
Posted: Fri Feb 20, 2004 12:50 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
b.foobar(u0);
b.foobar(u1);
when you call foobar with u0, I think 0 can be evaluated as a null, so foo
constructor will accept it, actually, you can debug it when passing 0, and
see how the program flows.
While you pass -1, there is no foo constructor which can take unsigned long
...
Just simple try that ..
const unsigned long u0 = 0;
const unsigned long u1 = 1;
char* pc0, pc1;
pc0=u0;
pc1=u1;
And see what kind of error you will get..
J.W.
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
b.foobar(u0);
b.foobar(u1);
}
/code
Torstein Hansen
(Remove "RemoveThis" to answer by mail)
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Sharad Kala Guest
|
Posted: Fri Feb 20, 2004 12:53 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
|
Actually you :-)
| Quote: | code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
b.foobar(u0);
b.foobar(u1);
}
|
A value of 0 can be implicitly converted to a char* so your b.foobar(u0);
works through. Same is not the case with your call b.foobar(u1).
Try this -
void *i = 0; // Works
void *j = 1; // Error
Best wishes,
Sharad
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maciej Sobczak Guest
|
Posted: Fri Feb 20, 2004 1:05 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
Hi,
Torstein Hansen wrote:
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
|
I think that the compiler got trapped in its own optimizations.
| Quote: | I really can't see why it would make any difference what numerical value
is used.
|
If you use const unsigned long (the const part is important here), then
the compiler may optimize the use of your variables away, substituting
plain values whenever the variable is used (if you've learned a bit of
assembly language, the difference is between indirect and immediate
addressing - the immediate one, when the hardcoded value is used, is
faster), so you example becomes:
b.foobar(0);
b.foobar(1);
The problem is that both calls need to use a foo constructor.
In the case of b.foobar(0), the foo(char *pc) constructor is used,
because 0 can be converted to a null pointer value (the Standard gives
the explicit license for this to happen and in most implementations NULL
is a macro that expands to 0).
In the case of b.foobar(1), none of the foo's constructors can be used
(there is no conversion from integral literal other than 0 to pointers)
and you get the message "Cannot convert from const unsigned long to
const class foo &".
| Quote: | Anyone care to explain? Is it me or the compiler that is half-blind?
|
It is the Standard that leads us to confusions like this and the
compiler that was trapped by its own optimizations. It should not
compile neither of the calls (try without "const" to see).
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Friedhelm Hoerner Guest
|
Posted: Fri Feb 20, 2004 1:10 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without warnings,
but using parameter u1 (equal to 1) gives a compiler error "Cannot
convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical value
is used.
Anyone care to explain? Is it me or the compiler that is half-blind?
code
class foo
{
public:
foo();
foo(const foo &f);
foo(char* pc);
};
class bar
{
public:
bar();
bool foobar(const foo& rf);
};
void main()
{
bar b;
const unsigned long u0 = 0;
const unsigned long u1 = 1;
|
you need a "const foo& rf" to call foobar...
.... u0 is 0 and may be interpreted as a NULL-Pointer therefore foo's
constructor
foo(char* pc) can be called to create the temporary object.
.... u1 is 1, there's no conversion to char*, therefore foo has no
matching constructor.
Friedhelm
[ 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 Feb 20, 2004 11:23 am Post subject: Re: Compiler error or? Microsoft VC++ v6.0 |
|
|
"Torstein Hansen" <torsteinRemoveThis (AT) hansen (DOT) as> wrote
| Quote: | The following code gives us a little headache.
Calls to foobar with parameter u0 (set to 0) compiles without
warnings, but using parameter u1 (equal to 1) gives a compiler error
"Cannot convert from const unsigned long to const class foo &"
I really can't see why it would make any difference what numerical
value is used.
|
The parameters in question are const, so u0 is a null pointer constant,
which can be converted to any pointer type.
Try dropping the const, and see what happens.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ 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
|
|