Namespaces
Variants

Conflicting declarations

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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:

(desde C++20)
  • Si ambos son funciones miembro no estáticas, deben satisfacer adicionalmente uno de los siguientes requisitos:
  • Exactamente uno de ellos es una función miembro de objeto implícita sin calificador de referencia y los tipos de sus parámetros de objeto, después de eliminar las referencias de nivel superior, son los mismos.
(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 correspondientes parámetros de plantilla están declarados ambos sin constraint , o ambos declarados con constraints equivalentes.
  • Tienen cláusulas requires trailing equivalentes (si las hay).
(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):

  • Ninguno es una declaración independiente del nombre.
(since C++26)
  • Se cumple una de las siguientes condiciones:
  • Aparecen en la misma unidad de traducción.
(desde C++20)

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 E como una variable, el otro también debe declarar E como una variable del mismo tipo.
  • Si uno declara E como una función , el otro también debe declarar E como una función del mismo tipo.
  • Si uno declara E como un enumerador , el otro también debe declarar E como un enumerador.
  • Si uno declara E como un namespace , el otro también debe declarar E como un namespace.
  • Si uno declara E como un class type , el otro también debe declarar E como un class type.
  • Si uno declara E como un enumeration type , el otro también debe declarar E como un enumeration type.
  • Si uno declara E como un class template , el otro también debe declarar E como un class template con una lista de parámetros de plantilla equivalente (ver function template overloading ).
  • Si uno declara E como una function template , el otro también debe declarar E como una function template con una lista de parámetros de plantilla y tipo equivalentes.
  • Si uno declara E como una plantilla de alias , el otro también debe declarar E como una plantilla de alias con una lista de parámetros de plantilla equivalente y type-id .
(desde C++11)
  • Si uno declara E como una (especialización parcial de una) plantilla de variable , el otro también debe declarar E como una (especialización parcial de una) plantilla de variable con una lista de parámetros de plantilla y tipo equivalentes.
(desde C++14)
  • Si uno declara E como un concepto , el otro también debe declarar E como un concepto.
(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