Conflicting declarations
A menos que se especifique lo contrario, dos declaraciones no pueden (re)introducir la misma entidad. El programa está mal formado si existen tales declaraciones.
Contenidos |
Declaraciones correspondientes
Dos declaraciones corresponden si (re)introducen el mismo nombre, ambas declaran constructores, o ambas declaran destructores, a menos que
- o bien es una using declaración ,
- una declara un tipo (no un typedef name ) y la otra declara una variable, miembro de datos no estático que no sea de una anonymous union , enumerador, función o plantilla de función, o
- cada una declara una función o plantilla de función y no declaran sobrecargas correspondientes.
Sobrecargas de función correspondientes
Dos declaraciones de función declaran sobrecargas correspondientes si ambas declaran funciones que satisfacen todas las siguientes condiciones:
- Tienen el mismo parameter-type-list , omitiendo los tipos de explicit object parameters (since C++23) .
|
(desde C++20) |
- Si ambos son funciones miembro no estáticas, deben satisfacer adicionalmente uno de los siguientes requisitos:
|
(desde C++23) |
-
- Sus parámetros de objeto tienen el mismo tipo.
Sobrecargas correspondientes de plantillas de función
Dos declaraciones de plantilla de función declaran sobrecargas correspondientes si ambas declaran plantillas de función que satisfacen todas las siguientes condiciones:
- Sus listas de parámetros de plantilla tienen la misma longitud.
- Sus parámetros de plantilla correspondientes son equivalentes .
- Tienen listas-de-tipos-de-parámetros equivalentes , omitiendo los tipos de parámetros de objeto explícitos (desde C++23) .
- Tienen tipos de retorno equivalentes.
|
(desde C++20) |
- Si ambos son plantillas de función miembro no estáticas, deben satisfacer adicionalmente uno de los siguientes requisitos:
|
(desde C++23) |
-
- Sus parámetros de objeto tienen tipos equivalentes.
struct A { friend void c(); // #1 }; struct B { friend void c() {} // corresponde a, y define, #1 }; typedef int Int; enum E : int { a }; void f(int); // #2 void f(Int) {} // define #2 void f(E) {} // OK, otra sobrecarga struct X { static void f(); void f() const; // error: redeclaración void g(); void g() const; // OK void g() &; // error: redeclaración void h(this X&, int); void h(int) &&; // OK, otra sobrecarga void j(this const X&); void j() const &; // error: redeclaración void k(); void k(this X&); // error: redeclaración };
Múltiples declaraciones de la misma entidad
|
Una declaración es independiente del nombre si su nombre es _ y declara
|
(desde C++26) |
A menos que se especifique lo contrario, dos declaraciones de entidades declaran la misma entidad si se satisfacen todas las siguientes condiciones, considerando que las declaraciones de tipos sin nombre introducen sus typedef names y enumeration names para propósitos de vinculación (si existen):
- Corresponden.
- Tienen el mismo target scope , que no es un function parameter scope ni un template parameter scope .
|
(since C++26) |
- Se cumple una de las siguientes condiciones:
-
- Aparecen en la misma unidad de traducción.
|
(desde C++20) |
-
- Ambos declaran nombres con external linkage .
Una declaración de una entidad o nombre typedef
X
es una
redeclaración
de
X
si otra declaración de
X
es accesible desde ella; de lo contrario, es una
primera declaración
de
X
.
Restricciones
Si dos declaraciones cualesquiera de una entidad
E
violan la restricción correspondiente a continuación, el programa está mal formado:
-
Si uno declara
Ecomo una variable, el otro también debe declararEcomo una variable del mismo tipo. -
Si uno declara
Ecomo una función , el otro también debe declararEcomo una función del mismo tipo. -
Si uno declara
Ecomo un enumerador , el otro también debe declararEcomo un enumerador. -
Si uno declara
Ecomo un namespace , el otro también debe declararEcomo un namespace. -
Si uno declara
Ecomo un class type , el otro también debe declararEcomo un class type. -
Si uno declara
Ecomo un enumeration type , el otro también debe declararEcomo un enumeration type. -
Si uno declara
Ecomo un class template , el otro también debe declararEcomo un class template con una lista de parámetros de plantilla equivalente (ver function template overloading ). -
Si uno declara
Ecomo una function template , el otro también debe declararEcomo una function template con una lista de parámetros de plantilla y tipo equivalentes.
|
(desde C++11) |
|
(desde C++14) |
|
(desde C++20) |
Los tipos se comparan después de todos los ajustes de tipos (durante los cuales typedefs son reemplazados por sus definiciones). Las declaraciones para un objeto array pueden especificar tipos de array que difieren por la presencia o ausencia de un major array bound. No se requiere diagnóstico si ninguna declaración es alcanzable desde la otra.
void g(); // #1 void g(int); // OK, entidad diferente de #1 (no corresponden) int g(); // Error: misma entidad que #1 con tipo diferente void h(); // #2 namespace h {} // Error: misma entidad que #2, pero no es una función
Si una declaración
H
que declara un nombre con
enlace interno
precede a una declaración
D
en otra unidad de traducción
U
y declararía la misma entidad que
D
si apareciera en
U
, el programa está mal formado.
Declaraciones potencialmente conflictivas
Dos declaraciones potencialmente entran en conflicto si corresponden pero declaran entidades diferentes.
Si, en cualquier ámbito, un nombre está vinculado a dos declaraciones
A
y
B
que potencialmente entran en conflicto
,
B
no es independiente del nombre
(desde C++26)
, y
A
precede a
B
, el programa está mal formado:
void f() { int x, y; void x(); // Error: entidad diferente para x int y; // Error: redefinición } enum { f }; // Error: entidad diferente para ::f namespace A {} namespace B = A; namespace B = A; // OK, sin efecto namespace B = B; // OK, sin efecto namespace A = B; // OK, sin efecto namespace B {} // Error: entidad diferente para B void g() { int _; _ = 0; // OK int _; // OK desde C++26, declaración independiente del nombre _ = 0; // Error: dos declaraciones no-función en el conjunto de búsqueda } void h () { int _; // #1 _ ++; // OK static int _; // Error: conflicto con #1 porque // las variables estáticas no son independientes del nombre }
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
|
CWG 279
( P1787R6 ) |
C++98 |
no estaba claro si una clase o enumeración sin nombre puede
ser redeclarada si tiene un nombre typedef para fines de enlace |
puede ser redeclarada |
|
CWG 338
( P1787R6 ) |
C++98 |
no estaba claro si una enumeración sin nombre puede ser
redeclarada si tiene un enumerador como nombre para fines de enlace |
puede ser redeclarada |
|
CWG 1884
( P1787R6 ) |
C++98 |
las restricciones aplicadas a múltiples
declaraciones de la misma entidad no estaban claras |
aclarado |