Flummoxed by a compiler error

K

Keith Degrace

VC++ 2003 fails to compile the following code. I figured it may just
be a bug in VC, so I tried with Comeau Online and I get a similar
result. Now I am wondering if I've perhaps encountered an oddity in
the C++ standard.

typedef int *IntPtr;

void foo(const IntPtr)
{
}

void bar(const int &value)
{
foo(&value);
}

VC++ reports:
error C2664: 'foo' : cannot convert parameter 1 from 'const int *__w64
' to 'const IntPtr'
Conversion loses qualifiers

Comeau reports:
"ComeauTest.c", line 9: error: argument of type "const int *" is
incompatible with parameter of type "IntPtr"

If I remove IntPtr, and change foo() to take a int * explicitly, it
compiles fine. If I remove the const, it compiles fine.

Any ideas?
 
J

jkherciueh

Keith said:
VC++ 2003 fails to compile the following code. I figured it may just
be a bug in VC, so I tried with Comeau Online and I get a similar
result. Now I am wondering if I've perhaps encountered an oddity in
the C++ standard.

typedef int *IntPtr;

void foo(const IntPtr)
{
}

void bar(const int &value)
{
foo(&value);
}

VC++ reports:
error C2664: 'foo' : cannot convert parameter 1 from 'const int *__w64
' to 'const IntPtr'
Conversion loses qualifiers

Comeau reports:
"ComeauTest.c", line 9: error: argument of type "const int *" is
incompatible with parameter of type "IntPtr"

If I remove IntPtr, and change foo() to take a int * explicitly,
it compiles fine.

You mean, when you write

foo ( const int * )

instead of

foo ( const IntPtr )


Note: typedef and #define are different.

If I remove the const, it compiles fine.

Any ideas?

Distinguish

a) a constant pointer to a non-const int
b) a non-const pointer to a const int

Ask yourself what

const IntPtr

is when IntPtr is int*.


Best

Kai-Uwe Bux
 
J

Joe Greer

VC++ 2003 fails to compile the following code. I figured it may just
be a bug in VC, so I tried with Comeau Online and I get a similar
result. Now I am wondering if I've perhaps encountered an oddity in
the C++ standard.

typedef int *IntPtr;

void foo(const IntPtr)
{
}

void bar(const int &value)
{
foo(&value);
}

VC++ reports:
error C2664: 'foo' : cannot convert parameter 1 from 'const int *__w64
' to 'const IntPtr'
Conversion loses qualifiers

Comeau reports:
"ComeauTest.c", line 9: error: argument of type "const int *" is
incompatible with parameter of type "IntPtr"

If I remove IntPtr, and change foo() to take a int * explicitly, it
compiles fine. If I remove the const, it compiles fine.

Any ideas?

Well, you have just encountered a 'feature' of typedefs. Let's rewrite
your code a bit a do some substitution:


void foo(const IntPtr) {}

can be rewritten as:

void foo(IntPtr const) {}

because of the way const works.

Now substitute your typedef:

void foo(Int * const) {}

Ahhhhh... We have a constant pointer, not a pointer to a const.

One way to think about it. If you are using a typedef, any cv
qualifiers you supply apply to the entire type. typedefs are not
macros, they are aliases for the type specified (in this case a
pointer).

joe
 
J

Jack Klein

VC++ 2003 fails to compile the following code. I figured it may just
be a bug in VC, so I tried with Comeau Online and I get a similar
result. Now I am wondering if I've perhaps encountered an oddity in
the C++ standard.

typedef int *IntPtr;

void foo(const IntPtr)
{
}

void bar(const int &value)
{
foo(&value);
}

VC++ reports:
error C2664: 'foo' : cannot convert parameter 1 from 'const int *__w64
' to 'const IntPtr'
Conversion loses qualifiers

Comeau reports:
"ComeauTest.c", line 9: error: argument of type "const int *" is
incompatible with parameter of type "IntPtr"

If I remove IntPtr, and change foo() to take a int * explicitly, it
compiles fine. If I remove the const, it compiles fine.

Any ideas?

The wording I like to use for this is quite simple. cv qualifiers do
not "penetrate" a typedef.

Given your typedef:

typedef int *IntPtr;

You think that using "const IntPtr ip" is equivalent to just putting
the const keyword in front, like this:

const int *ip

....meaning ip is pointer to const int, but it is not. A qualifier
like const, volatile, and restrict, if that ever gets added to C++,
does not "penetrate" a typedef. Any qualifiers applied to a
declaration involving the typedef always apply to the object defined,
so:

const IntPtr ip;

....is equivalent to:

int * const ip;

....meaning ip is a const pointer to a non-const int.

Using your typedef, there is absolutely no way to define a non-const
pointer to a const int.

This is one of the reasons why it is almost always a bad idea to
typedef pointers to any type of objects. There are exceptions, but
they are very few.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
J

Jerry Coffin

[ ... ]
This is one of the reasons why it is almost always a bad idea to
typedef pointers to any type of objects. There are exceptions, but
they are very few.

Just pay close attention to Jack's precise wording: functions are not
objects, and creating a typedef of a pointer to a function does not fall
within what he said.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top