Problem with typedef'ed pointer used as const return type

A

Adrian

Hi All,

I have the following code which I thought was ok. It compiles without
error on gcc.4.1.1 but has a warning/error with gcc4.3.1

I assumed it was a compiler bug and reported it as such, but was told
that it is not. Can someone point me to the page in the standard that
covers this. And what should it be correctly for func2 to compile.

// gcc 4.3.1 error
// dluadrianc:/home/adrianc> g++ -Wall -ansi -pedantic -Wextra -Werror
const.cc
// cc1plus: warnings being treated as errors
// const.cc:10: error: type qualifiers ignored on function return type


Thanks

Adrian Cornish

class Foo { };

const Foo *func1()
{
return 0;
}

typedef Foo *Bar;

const Bar func2()
{
return 0;
}

int main(int , char *[])
{
func1();
func2();

return 0;
}
 
A

Abhishek Padmanabh

Hi All,

I have the following code which I thought was ok. It compiles without
error on gcc.4.1.1 but has a warning/error with gcc4.3.1

// const.cc:10: error: type qualifiers ignored on function return type

class Foo { };

const Foo *func1()
{
   return 0;

}

typedef Foo *Bar;

const Bar func2()
{
   return 0;

}

Type qualifier on the return type is meaningless unless the return
yields an l-value. In the first case, const applies to the object
being pointed to by the pointer and the return is a pointer. In second
case, const applies to the pointer type being returned, hence the
compiler suggests that it would be ignored.
And what should it be correctly for func2 to compile.

To keep the const-ness on the object being pointed to you can change
the typedef to:

typedef const Foo * Bar;
//Or,
typedef Foo const * Bar;

Otherwise, just remove the const specifier for the Bar return type to
make it compile. I am not sure about exact the relevant section, but
3.10/9 [basic.lval] from n2521 draft looks close.
 
M

Michael DOUBEZ

Adrian said:
Hi All,

I have the following code which I thought was ok. It compiles without
error on gcc.4.1.1 but has a warning/error with gcc4.3.1

I assumed it was a compiler bug and reported it as such, but was told
that it is not. Can someone point me to the page in the standard that
covers this.

From 3.10/5:
The result of calling a function that does not return a reference is an
rvalue. [...]

and 3.10/9:
Class rvalues can have cv-qualified types; non-class rvalues always have
cv-unqualified types. [...]

In the case func2, you return a pointer which is an rvalue and thus
cannot be cv-qualified; IMO the confusion is that you return a const
pointer to Foo and not a pointer to const Foo.
And what should it be correctly for func2 to compile.

To compile:
Bar func2()
{
//...
}
is enough
// gcc 4.3.1 error
// dluadrianc:/home/adrianc> g++ -Wall -ansi -pedantic -Wextra -Werror
const.cc
// cc1plus: warnings being treated as errors
// const.cc:10: error: type qualifiers ignored on function return type


Thanks

Adrian Cornish

class Foo { };

const Foo *func1()
{
return 0;
}

Here you return a pointer on a const Foo. This is equivalent to:
Foo const * func1()
typedef Foo *Bar;

const Bar func2()
{
return 0;
}

Here you return a const value of a Foo pointer. This is equivalent to:
Foo * const func2()

Note the difference with func1.
int main(int , char *[])
{
func1();
func2();

return 0;
}
 
A

Adrian

 From 3.10/5:
The result of calling a function that does not return a reference is an
rvalue. [...]

and 3.10/9:
Class rvalues can have cv-qualified types; non-class rvalues always have
cv-unqualified types. [...]

In the case func2, you return a pointer which is an rvalue and thus
cannot be cv-qualified; IMO the confusion is that you return a const
pointer to Foo and not a pointer to const Foo.

Thanks. That is so obvious now you pointed it out.

I guess also the const should be in the type def if I wanted to match
func1() as in

typedef const Foo* Ray;
Ray func3()
{
return 0;
}


:)
Adrian Cornish
 
A

Adrian

It's not an error.  It's a warning.  Disable it if you need to pass by
the GCC's idiosyncrasies.

Having a 'const' qualifier in the return type is not something I would
consider bad (and I think many agree).  Your function is similar to

    const int blah();

'const' has no real meaning when you're returning an rvalue.
I agree with that. I use the extra -Werror option to catch other bad
things. I maintain some very old code and like to fix it up. But it
kept stopping on this error which was from a 3rd party library.

Although the -Werror did help me catch a nasty bit. :)
class Foo
{
~Foo() {if(m_pointer) delete m_pointer; }
void *m_pointer;
}
 
N

Noah Roberts

Adrian said:
Hi All,

I have the following code which I thought was ok. It compiles without
error on gcc.4.1.1 but has a warning/error with gcc4.3.1

I assumed it was a compiler bug and reported it as such, but was told
that it is not. Can someone point me to the page in the standard that
covers this. And what should it be correctly for func2 to compile.

// gcc 4.3.1 error
// dluadrianc:/home/adrianc> g++ -Wall -ansi -pedantic -Wextra -Werror
const.cc
// cc1plus: warnings being treated as errors
// const.cc:10: error: type qualifiers ignored on function return type


Thanks

Adrian Cornish

class Foo { };

const Foo *func1()
{
return 0;
}

typedef Foo *Bar;

const Bar func2()

This doesn't say what you think it does. If you used post-const
notation instead of pre-const you'd notice the difference right away.
Consider, const always refers to the type immediately following or before.

const Foo * == Foo const* (const refers to the Foo being pointed to)

typedef Foo * Bar;
const Bar == Foo * const (const refers to the pointer, Foo is non-const)
 
G

Greg Herlihy

Here your function returns a pointer to a const Foo.  The proper way to
declare your function would be

    Foo const * func1()

(where 'const' follows the type it qualifies).

"Foo const *" is a properly confusing way to specify a pointer to a
const Foo (though, admittedly, it's a great way to specify to a
pointer to a Foo const). After all, how on earth can sandwiching the
"const" qualifier between two potential targets (Foo) and (*) be
better than having "const" unambiguously refer to "Foo" by appearing
right in front of it?

And if there is something improper about a "const Foo" declaration,
then why do all the Standard Library interfaces and examples in the C+
+ Standard invariably place a "const" before the target type, and not
afterwards?

Greg
 
J

James Kanze

"Foo const *" is a properly confusing way to specify a pointer to a
const Foo (though, admittedly, it's a great way to specify to a
pointer to a Foo const).

Which is what it specifies. A pointer to a Foo const. (C++
declarations generally read backwards, e.g. int* is "pointer to
int", with "*" reading "pointer to", "int a[2]" is "array[2] of
int", with "[2]" reading "array[2] of", "int *const" is "const
pointer to int" and "int const*" is "pointer to const it".)
After all, how on earth can sandwiching the "const" qualifier
between two potential targets (Foo) and (*) be better than
having "const" unambiguously refer to "Foo" by appearing right
in front of it?

Well, you've got to sandwich it in sometimes. More generally,
however, cv-qualifiers modify what precedes them, except in the
declarator-spec, where the order is indifferent.

Of course, it would be more logical if one could write:

*int p;
[2] int a ;
const* int cpi ;
* const int pci ;

But that would cause a lot of other problems in parsing.
And if there is something improper about a "const Foo"
declaration, then why do all the Standard Library interfaces
and examples in the C++ Standard invariably place a "const"
before the target type, and not afterwards?

History. Maybe we should change it in the next version:).
 

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,989
Messages
2,570,207
Members
46,786
Latest member
EmilioGuru

Latest Threads

Top