2010-01-23 12 views
5

GCC trata estas dos declaraciones de funciones como equivalentes:punteros const en la resolución de sobrecarga

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

Esto tiene algún sentido, porque una persona que llama siempre va a ignorar la const en este caso ... sólo afecta al uso del parámetro 'a' dentro de la función.

Lo que me pregunto es dónde (si es que en alguna parte) el estándar dice que está específicamente bien descartar los calificadores en los punteros utilizados como argumentos de función con el fin de resolver la sobrecarga.

(Mi problema real es que me gustaría averiguar dónde GCC elimina estos calificadores inútiles internamente, y dado que la interfaz C++ de GCC está llena de comentarios que hacen referencia al estándar, la sección relevante del estándar podría ayudarme a encontrar . el punto correcto)

+0

AFAIK no es solo para punteros. – Troubadour

Respuesta

4

El estándar dice en 8.3.5/3 que a los efectos de determinar la función tipo cualesquiera cv-calificadores que califiquen directamente el tipo de parámetro se eliminan. Es decir. que literalmente dice que una función declarada como

void foo(int *const a); 

tiene función de tipo void (int *).

Una persona pedante podría argumentar que esto no es lo suficientemente concluyentes para afirmar que la declaración anterior debe coincidir con la definición como ésta

void foo(int *a) 
{ 
} 

o que debería hacer que el código con la declaración doble (como en el ejemplo) mal formado, ya que ninguno de estos conceptos se describe en el estándar en términos de tipos de función.

Quiero decir, todos sabemos que estos const estaban destinados a ser ignorados para todos los propósitos externos, pero hasta ahora no he podido encontrar la redacción en el estándar que declararía de manera concluyente exactamente eso. Tal vez me perdí algo.

En realidad, en 13.1/3 tiene una "Nota" que dice que las declaraciones de función con declaraciones de parámetros equivalentes (como se define en 8.3.5) declaran la misma función. Pero es solo una nota, no es normativa, lo que sugiere que en algún lugar de la norma debería haber algún texto normativo sobre el mismo tema.

+0

Gracias, 8.3.5/3 es exactamente lo que estaba buscando. –

+0

Hmm, parece que la nota se basa en 13/1, lo que, aunque no es muy claro, dice "Por extensión, dos declaraciones en el mismo ámbito que declaran el mismo nombre pero con diferentes tipos se llaman declaraciones sobrecargadas". Tener el mismo tipo hace que no se sobrecarguen las declaraciones. Para hacer coincidir las declaraciones entre sí 13.2/1 dice "Dos declaraciones de función del mismo nombre se refieren a la misma función si están en el mismo ámbito y tienen declaraciones de parámetros equivalentes.", Y hace referencia a la nota anterior para borrar "equivalente". –

+0

Sin embargo, esta práctica también la realiza C Standard. Para describir cómo se ve la definición de la función 'main', dice que deberían declararse como" ... o equivalentes ", y una nota al pie dice cómo se entiende (es decir, que en lugar de' char * [] 'podemos escribir' char ** ', y así sucesivamente). –

2

es lo mismo que:

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

al ser la misma a la persona que llama. Esto se debe a que la función obtiene una copia por valor sin importar qué, por lo que a la persona que llama no le importa si se considera const o no; no hace ninguna diferencia a eso.

No es no legal para que el compilador ignore tales cosas, pero no hay diferencia en la resolución de sobrecarga. El const se aplica a la implementación de la función.

ilegal sería si el compilador tratado:

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

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

El mismo, al ignorar el const.

1

Creo que es al revés. Cualquier puntero, incluso nonconst, se puede tratar como const :).

+0

Creo que estás confundiendo 'int * const' con' const int * '? El problema aquí es con la constness del puntero mismo. – Troubadour

+0

Trovador: vi que la constness pertenece al puntero. Mi punto cualquier cosa (incluso nonconst) se puede ver como const en la función – Drakosha

3

creo que es básicamente como prohibidos como esto:

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

const sobre los no referencias no participa en la sobrecarga.

De hecho incluso se podría declarar

void foo(int a); 

y posteriormente definir

void foo(const int a) {} 

donde el constness es puramente un detalle de implementación, que la persona que llama no se preocupa.

Cuestiones relacionadas