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

Sofern nicht anders angegeben, können zwei Deklarationen nicht dieselbe Entität (wieder)einführen. Das Programm ist fehlerhaft, wenn solche Deklarationen existieren.

Inhaltsverzeichnis

Entsprechende Deklarationen

Zwei Deklarationen korrespondieren , wenn sie denselben Namen (wieder)einführen, beide Konstruktoren deklarieren oder beide Destruktoren deklarieren, es sei denn

  • entweder ist es eine using Deklaration ,
  • eine deklariert einen Typ (keinen typedef-Namen ) und die andere deklariert eine Variable, ein nicht-statisches Datenelement außer eines anonymen Unions , einen Enumerator, eine Funktion oder eine Funktionsvorlage, oder
  • jede deklariert eine Funktion oder Funktionsvorlage und sie deklarieren keine entsprechenden Überladungen.

Entsprechende Funktionsüberladungen

Zwei Funktionsdeklarationen deklarieren entsprechende Überladungen wenn beide Funktionen deklarieren, die alle folgenden Bedingungen erfüllen:

(seit C++20)
  • Wenn beide von ihnen nicht-statische Memberfunktionen sind, müssen sie zusätzlich eine der folgenden Anforderungen erfüllen:
  • Genau eine davon ist eine implizite Objekt-Memberfunktion ohne Ref-Qualifier und die Typen ihrer Objektparameter sind nach Entfernen der Top-Level-Referenzen gleich.
(seit C++23)
  • Ihre Objektparameter haben denselben Typ.

Entsprechende Funktions-Template-Überladungen

Zwei Funktions-Template-Deklarationen deklarieren entsprechende Überladungen wenn beide Funktions-Templates deklarieren, die alle folgenden Bedingungen erfüllen:

  • Ihre entsprechenden Template-Parameter sind entweder beide ohne Constraint deklariert, oder beide mit äquivalenten Constraints deklariert.
  • Sie haben äquivalente nachgestellte requires -Klauseln (falls vorhanden).
(seit C++20)
  • Wenn beide nicht-statische Member-Funktionstemplates sind, müssen sie zusätzlich eine der folgenden Anforderungen erfüllen:
  • Genau eine von ihnen ist eine implizite Objekt-Memberfunktion -Template ohne Ref-Qualifier und die Typen ihrer Objektparameter sind nach Entfernen aller Referenzen äquivalent.
(seit C++23)
  • Ihre Objektparameter haben äquivalente Typen.
struct A
{
    friend void c();   // #1
};
struct B
{
    friend void c() {} // entspricht #1 und definiert es
};
typedef int Int;
enum E : int { a };
void f(int);   // #2
void f(Int) {} // definiert #2
void f(E) {}   // OK, weitere Überladung
struct X
{
    static void f();
    void f() const;   // Fehler: Neudeklaration
    void g();
    void g() const;   // OK
    void g() &;       // Fehler: Neudeklaration
    void h(this X&, int);
    void h(int) &&;   // OK, weitere Überladung
    void j(this const X&);
    void j() const &; // Fehler: Neudeklaration
    void k();
    void k(this X&);  // Fehler: Neudeklaration
};

Mehrfache Deklarationen derselben Entität

Eine Deklaration ist namensunabhängig , wenn ihr Name _ ist und sie deklariert

(seit C++26)

Sofern nicht anders angegeben, deklarieren zwei Deklarationen von Entitäten dieselbe Entität wenn alle folgenden Bedingungen erfüllt sind, wobei Deklarationen unbenannter Typen ihre typedef-Namen und Aufzählungsnamen für Linkage-Zwecke einführen (falls vorhanden):

  • Keines ist eine namensunabhängige Deklaration.
(since C++26)
  • Eine der folgenden Bedingungen ist erfüllt:
  • Sie erscheinen in derselben Übersetzungseinheit.
(seit C++20)

Eine Deklaration eines Entitäts- oder Typedef-Namens X ist eine Neudeklaration von X , wenn eine andere Deklaration von X von ihr aus erreichbar ist; andernfalls ist es eine Erstdoklaration von X .

Einschränkungen

Wenn zwei Deklarationen einer Entität E die entsprechende nachfolgende Einschränkung verletzen, ist das Programm fehlerhaft:

  • Wenn man E als Variable deklariert, muss der andere ebenfalls E als Variable desselben Typs deklarieren.
  • Wenn man E als eine Funktion deklariert, muss der andere ebenfalls E als Funktion desselben Typs deklarieren.
  • Wenn man E als einen Enumerator deklariert, muss der andere ebenfalls E als Enumerator deklarieren.
  • Wenn man E als einen Namespace deklariert, muss der andere ebenfalls E als Namespace deklarieren.
  • Wenn man E als einen Klassentyp deklariert, muss der andere ebenfalls E als Klassentyp deklarieren.
  • Wenn man E als einen Aufzählungstyp deklariert, muss der andere ebenfalls E als Aufzählungstyp deklarieren.
  • Wenn man E als eine Klassenvorlage deklariert, muss der andere ebenfalls E als Klassenvorlage mit einer äquivalenten Template-Parameterliste deklarieren (siehe Funktionsvorlagen-Überladung ).
  • Wenn man E als eine Funktionsvorlage deklariert, muss der andere ebenfalls E als Funktionsvorlage mit einer äquivalenten Template-Parameterliste und Typ deklarieren.
  • Wenn eine Deklaration E als Alias-Template definiert, muss die andere Deklaration ebenfalls E als Alias-Template mit einer äquivalenten Template-Parameterliste und Typ-ID deklarieren.
(seit C++11)
  • Wenn eine Deklaration E als (partielle Spezialisierung eines) Variablen-Templates definiert, muss die andere Deklaration ebenfalls E als (partielle Spezialisierung eines) Variablen-Templates mit einer äquivalenten Template-Parameterliste und Typ deklarieren.
(seit C++14)
  • Wenn eine Deklaration E als ein Konzept definiert, muss die andere Deklaration ebenfalls E als Konzept deklarieren.
(seit C++20)

Typen werden nach allen Anpassungen der Typen verglichen (wobei typedefs durch ihre Definitionen ersetzt werden). Deklarationen für ein Array-Objekt können Array-Typen angeben, die sich durch das Vorhandensein oder Fehlen einer Hauptarray-Grenze unterscheiden. Es ist keine Diagnose erforderlich, wenn keine der Deklarationen von der anderen aus erreichbar ist.

void g();      // #1
void g(int);   // OK, andere Entität als #1 (sie entsprechen sich nicht)
int g();       // Fehler: dieselbe Entität wie #1 mit anderem Typ
void h();      // #2
namespace h {} // Fehler: dieselbe Entität wie #2, aber keine Funktion

Wenn eine Deklaration H , die einen Namen mit internal linkage deklariert, einer Deklaration D in einer anderen Übersetzungseinheit U vorausgeht und dieselbe Entität wie D deklarieren würde, wenn sie in U erschiene, ist das Programm fehlerhaft.

Potenziell widersprüchliche Deklarationen

Zwei Deklarationen potentially conflict wenn sie korrespondieren aber unterschiedliche Entitäten deklarieren.

Wenn in einem beliebigen Gültigkeitsbereich ein Name an zwei Deklarationen A und B gebunden wird, die potenziell in Konflikt stehen , B nicht namensunabhängig ist (seit C++26) , und A vor B steht, ist das Programm fehlerhaft:

void f()
{
    int x, y;
    void x(); // Fehler: verschiedene Entität für x
    int y;    // Fehler: Neudefinition
}
enum { f };   // Fehler: verschiedene Entität für ::f
namespace A {}
namespace B = A;
namespace B = A; // OK, keine Auswirkung
namespace B = B; // OK, keine Auswirkung
namespace A = B; // OK, keine Auswirkung
namespace B {}   // Fehler: verschiedene Entität für B
void g()
{
    int _;
    _ = 0; // OK
    int _; // OK seit C++26, namensunabhängige Deklaration
    _ = 0; // Fehler: zwei Nicht-Funktionsdeklarationen im Lookup-Set
}
void h ()
{
    int _;        // #1
    _ ++;         // OK
    static int _; // Fehler: Konflikt mit #1 weil
                  // statische Variablen nicht namensunabhängig sind
}

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 279
( P1787R6 )
C++98 es war unklar, ob eine unbenannte Klasse oder Enumeration
erneut deklariert werden kann, wenn sie einen Typnamen für Verbindungszwecke hat
sie kann erneut deklariert werden
CWG 338
( P1787R6 )
C++98 es war unklar, ob eine unbenannte Enumeration erneut
deklariert werden kann, wenn sie einen Enumerator als Namen für Verbindungszwecke hat
sie kann erneut deklariert werden
CWG 1884
( P1787R6 )
C++98 die Einschränkungen für mehrere
Deklarationen derselben Entität waren unklar
klargestellt