Conflicting declarations
Unless otherwise specified, two declarations cannot (re)introduce the same entity. The program is ill-formed if such declarations exist.
Contents |
Corresponding declarations
Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
- either is a using declaration,
- one declares a type (not a typedef name) and the other declares a variable, non-static data member other than of an anonymous union, enumerator, function, or function template, or
- each declares a function or function template and they do not declare corresponding overloads.
Corresponding function overloads
Two function declarations declare corresponding overloads if both declare functions satisfying all following conditions:
- They have the same parameter-type-list, omitting the types of explicit object parameters(since C++23).
|
(since C++20) |
- If both of them are non-static member functions, they need to additionally satisfy one of the following requirements:
|
(since C++23) |
- Their object parameters have the same type.
Corresponding function template overloads
Two function template declarations declare corresponding overloads if both declare function templates satisfying all following conditions:
- Their template parameter lists have the same length.
- Their corresponding template parameters are equivalent.
- They have equivalent parameter-type-lists, omitting the types of explicit object parameters(since C++23).
- They have equivalent return types.
|
(since C++20) |
- If both are non-static members function templates, they need to additionally satisfy one of the following requirements:
|
(since C++23) |
- Their object parameters have equivalent types.
struct A { friend void c(); // #1 }; struct B { friend void c() {} // corresponds to, and defines, #1 }; typedef int Int; enum E : int { a }; void f(int); // #2 void f(Int) {} // defines #2 void f(E) {} // OK, another overload struct X { static void f(); void f() const; // error: redeclaration void g(); void g() const; // OK void g() &; // error: redeclaration void h(this X&, int); void h(int) &&; // OK, another overload void j(this const X&); void j() const &; // error: redeclaration void k(); void k(this X&); // error: redeclaration };
Multiple declarations of the same entity
A declaration is name-independent if its name is _ and it declares
|
(since C++26) |
Unless otherwise specified, two declarations of entities declare the same entity if all following conditions are satisfied, considering declarations of unnamed types to introduce their typedef names and enumeration names for linkage purposes (if any exists):
- They correspond.
- They have the same target scope, which is not a function parameter scope or a template parameter scope.
|
(since C++26) |
- One of the following conditions is satisfied:
- They appear in the same translation unit.
|
(since C++20) |
- They both declare names with external linkage.
A declaration of an entity or typedef name X
is a redeclaration of X
if another declaration of X
is reachable from it.
Restrictions
If any two declarations of an entity E
violate the corresponding restriction below, the program is ill-formed:
- If one declares
E
to be a variable, the other must also declareE
as a variable of the same type. - If one declares
E
to be a function, the other must also declareE
as a function of the same type. - If one declares
E
to be an enumerator, the other must also declareE
as an enumerator. - If one declares
E
to be a namespace, the other must also declareE
as a namespace. - If one declares
E
to be a class type, the other must also declareE
as a class type. - If one declares
E
to be an enumeration type, the other must also declareE
as an enumeration type. - If one declares
E
to be a class template, the other must also declareE
as a class template with an equivalent template parameter list (see function template overloading). - If one declares
E
to be a function template, the other must also declareE
as a function template with an equivalent template parameter list and type.
|
(since C++11) |
|
(since C++14) |
|
(since C++20) |
Types are compared after all adjustments of types (during which typedefs are replaced by their definitions). Declarations for an array object can specify array types that differ by the presence or absence of a major array bound. No diagnostic is required if neither declaration is reachable from the other.
void g(); // #1 void g(int); // OK, different entity from #1 (they do not correspond) int g(); // Error: same entity as #1 with different type void h(); // #2 namespace h {} // Error: same entity as #2, but not a function
If a declaration H
that declares a name with internal linkage precedes a declaration D
in another translation unit U
and would declare the same entity as D
if it appeared in U
, the program is ill-formed.
Potentially-conflicting declarations
Two declarations potentially conflict if they correspond but declare different entities.
If, in any scope, a name is bound to two declarations A
and B
that potentially conflict, B
is not name-independent(since C++26), and A
precedes B
, the program is ill-formed:
void f() { int x, y; void x(); // Error: different entity for x int y; // Error: redefinition } enum { f }; // Error: different entity for ::f namespace A {} namespace B = A; namespace B = A; // OK, no effect namespace B = B; // OK, no effect namespace A = B; // OK, no effect namespace B {} // Error: different entity for B void g() { int _; _ = 0; // OK int _; // OK since C++26, name-independent declaration _ = 0; // Error: two non-function declarations in the lookup set } void h () { int _; // #1 _ ++; // OK static int _; // Error: conflicts with #1 because // static variables are not name-independent }
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 279 (P1787R6) |
C++98 | it was unclear whether an unnamed class or enumeration can be redeclared if it has a typedef name for linkage purposes |
it can be redeclared |
CWG 338 (P1787R6) |
C++98 | it was unclear whether an unnamed enumeration can be redeclared if it has an enumerator as a name for linkage purposes |
it can be redeclared |
CWG 1884 (P1787R6) |
C++98 | the restrictions applied to multiple declarations of the same entity were unclear |
made clear |