tags:

views:

80

answers:

4

GCC treats these two function declarations as equivalent:

void F(int* a) { }
void F(int* const a) { }

test.cpp: In function 'void F(int*)':

test.cpp:235: error: redefinition of 'void F(int*)'

test.cpp:234: error: 'void F(int*)' previously defined here

This makes some sense because a caller will always ignore the const in this case... it only affects the usage of the parameter 'a' inside of the function.

What I'm wondering is where (if anywhere) the standard says that it's specifically OK to discard qualifiers on pointers used as function arguments for the purpose of overload resolution.

(My real issue is that I'd like to figure out where GCC strips these pointless qualifiers internally, and since the C++ frontend of GCC is littered with comments referencing the standard, the relevant section of the standard might help me find the correct spot.)

+2  A: 

It's the same as:

void foo(int);
void foo(const int);

Being the same to the caller. This is because the function is getting a copy by-value no matter what, so the caller doesn't care if it's thought of as const or not; it makes no difference to it.

It's not legal for the compiler to ignore such things, but there is no difference in overload resolution. The const applies to the implementation of the function.

Illegal would be if the compiler treated:

void foo(int i)
{
    i = 5; // good
}

void foo(const int)
{
    i = 5; // lolwut?
}

The same, by ignoring the const.

GMan
+1  A: 

I believe it's the other way around. Any pointer, even nonconst, can be treated like const :).

Drakosha
I think you're confusing `int * const` with `const int *`? The issue here is with the constness of the pointer itself.
Troubadour
Troubadour: i did see the constness belongs to the pointer. My point anything (even nonconst) can be seen as const in the function
Drakosha
+3  A: 

I think it is basically as prohibited as this:

void foo(int a) {}
void foo(const int a) {}

const on non-references doesn't participate in overloading.

In fact you could even declare

void foo(int a);

and later define

void foo(const int a) {}

where the constness is purely an implementation detail which the caller doesn't care about.

UncleBens
+4  A: 

Standard says in 8.3.5/3 that for the purposes of determining the function type any cv-qualifiers that directly qualify the parameter type are deleted. I.e. it literally says that a function declared as

void foo(int *const a);

has function type void (int *).

A pedantic person might argue that this is not conclusive enough to claim that the above declaration should match the definition like this one

void foo(int *a)
{
}

or that it should make the code with dual declaration (as in your example) ill-formed, since neither of these concepts are described in the standard in terms of function types.

I mean, we all know that these const were intended to be ignored for all external purposes, but so far I was unable to find the wording in the standard that would conclusively state exactly that. Maybe I missed something.

Actually, in 13.1/3 it has a "Note" that says that function declarations with equivalent parameter declarations (as defined in 8.3.5) declare the same function. But it is just a note, it is non-normative, which suggests that somewhere in the standard there should be some normative text on the same issue.

AndreyT
Thanks, 8.3.5/3 is exactly what I was looking for.
Dan Olson
Hmm, looks like the note is based on 13/1 which, admittedly not quite clearly, says "By extension, two declarations in the same scope that declare the same name but with different types are called overloaded declarations.". Having the same type makes them not overloaded declarations. To match the declarations against each other 13.2/1 says "Two function declarations of the same name refer to the same function if they are in the same scope and have equivalent parameter declarations.", and references the previous note for clearifying "equivalent".
Johannes Schaub - litb
This practice is also done by the C Standard, though. For describing how the `main` function definition looks, it says they should be declared like "... or equivalent", and a footnote says how that is meant (i.e that instead of `char*[]` we can write `char**`, and so on).
Johannes Schaub - litb
In fact, this is how i read the stuff: 13.1 refers to both function declarations declaring a function and declaring a template: It says in what cases declarations are overloadable and where not. 13.2 does the declaration matching only for such function declarations that declare functions ("... refer to the same function of they ..."). For templates, 14.5.5.1 does the declaration matching. Note that the example in 14.5.5.1/4 shows declarations with the *same* type that it says overload each other. This would need a normative rule that says such things are also overloaded declarations i think.
Johannes Schaub - litb
I've written an answer about this matter for signatures (which of course are not directly related to overloading, but it contains the function-declaration stuff too) some time ago: http://stackoverflow.com/questions/290038/is-the-return-type-part-of-the-function-signature/290048#290048 . So in any case, i find 13/1, 13.1 and 13.2 largely confusing anyway :) In fact, i think 13[over]/1 is broken. It basically forbids doing `struct F { }; void F() { }` by saying that type declarations cannot be overloaded. (I think it may intend to say *typedef* declarations, instead).
Johannes Schaub - litb