Namensräume
Varianten
Aktionen

Konfligierende Deklarationen

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

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

Inhalt

[bearbeiten] Entsprechende Deklarationen

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

  • eine ist eine using-Deklaration,
  • eine deklariert einen Typ (keinen typedef-Namen) und die andere deklariert eine Variable, einen nicht-statischen Datenmember (außer in einer anonymen Union), einen Enumerator, eine Funktion oder ein Funktions-Template,
  • oder beide deklarieren eine Funktion oder ein Funktions-Template und sie deklarieren keine entsprechenden Überladungen.

[bearbeiten] Entsprechende Funktionsüberladungen

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

(seit C++20)
  • Wenn beide Nicht-Statische Memberfunktionen sind, müssen sie zusätzlich eine der folgenden Anforderungen erfüllen
  • Genau eine von ihnen ist eine implizite Objektmemberfunktion ohne ref-qualifier und die Typen ihrer Objektparameter, nach Entfernung von Top-Level-Referenzen, sind identisch.
(seit C++23)
  • Ihre Objektparameter haben denselben Typ.

[bearbeiten] Entsprechende Funktions-Template-Überladungen

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

  • Ihre Template-Parameterlisten haben die gleiche Länge.
  • Ihre entsprechenden Template-Parameter sind äquivalent.
  • Sie haben äquivalente Parameterlisten, wobei die Typen von expliziten Objektparametern weggelassen werden(seit C++23).
  • Sie haben äquivalente Rückgabetypen.
  • 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 Memberfunktions-Templates sind, müssen sie zusätzlich eine der folgenden Anforderungen erfüllen
(seit C++23)
  • Ihre Objektparameter haben äquivalente Typen.
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
};

[bearbeiten] Mehrfache Deklarationen derselben Entität

Eine Deklaration ist namenunabhä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 Enumerationsnamen zu Linkage-Zwecken (falls vorhanden) einführen

  • Keine ist eine namenunabhängige Deklaration.
(seit C++26)
  • Eine der folgenden Bedingungen ist erfüllt
  • Sie erscheinen in derselben Translation Unit.
(seit C++20)

Eine Deklaration einer Entität oder eines Typedef-Namens X ist eine Wiederdeklaration von X, wenn eine andere Deklaration von X von ihr erreichbar ist; andernfalls ist es eine erste Deklaration  von X.

[bearbeiten] Beschränkungen

Wenn zwei Deklarationen einer Entität E die entsprechende Beschränkung unten verletzen, ist das Programm fehlerhaft

  • Wenn eine E als Variable deklariert, muss die andere E auch als Variable desselben Typs deklarieren.
  • Wenn eine E als Funktion deklariert, muss die andere E auch als Funktion desselben Typs deklarieren.
  • Wenn eine E als Enumerator deklariert, muss die andere E auch als Enumerator deklarieren.
  • Wenn eine E als Namespace deklariert, muss die andere E auch als Namespace deklarieren.
  • Wenn eine E als Klassentyp deklariert, muss die andere E auch als Klassentyp deklarieren.
  • Wenn eine E als Enumerationstyp deklariert, muss die andere E auch als Enumerationstyp deklarieren.
  • Wenn eine E als Klassentemplate deklariert, muss die andere E auch als Klassentemplate mit einer äquivalenten Template-Parameterliste deklarieren (siehe Funktions-Template-Überladung).
  • Wenn eine E als Funktions-Template deklariert, muss die andere E auch als Funktions-Template mit einer äquivalenten Template-Parameterliste und einem äquivalenten Typ deklarieren.
  • Wenn eine E als Alias-Template deklariert, muss die andere E auch als Alias-Template mit einer äquivalenten Template-Parameterliste und type-id deklarieren.
(seit C++11)
  • Wenn eine E als (partielle Spezialisierung eines) Variablentemplates deklariert, muss die andere E auch als (partielle Spezialisierung eines) Variablentemplates mit einer äquivalenten Template-Parameterliste und einem äquivalenten Typ deklarieren.
(seit C++14)
  • Wenn eine E als Konzept deklariert, muss die andere E auch als Konzept deklarieren.
(seit C++20)

Typen werden nach allen Anpassungen von 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 Haupt-Array-Grenze unterscheiden. Keine Diagnose ist erforderlich, wenn keine der Deklarationen von der anderen erreichbar ist.

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

Wenn eine Deklaration H, die einen Namen mit interner Linkage deklariert, einer Deklaration D in einer anderen Translation Unit U vorausgeht und dieselbe Entität wie D deklarieren würde, wenn sie in U erscheinen würde, ist das Programm fehlerhaft.

[bearbeiten] Potenziell konfliktreiche Deklarationen

Zwei Deklarationen potenziell konfliktieren, wenn sie korrespondieren, aber verschiedene Entitäten deklarieren.

Wenn in irgendeinem Scope ein Name an zwei Deklarationen A und B gebunden ist, die potenziell konfliktieren, B nicht namensunabhängig ist(seit C++26) und A vor B liegt, ist das Programm fehlerhaft

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
}

[bearbeiten] Fehlerberichte

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

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 279
(P1787R6)
C++98 Es war unklar, ob eine unbenannte Klasse oder Aufzählung
wiederdeklariert werden kann, wenn sie einen typedef-Namen für Linkage-Zwecke hat
sie kann wiederdeklariert werden
CWG 338
(P1787R6)
C++98 Es war unklar, ob eine unbenannte Aufzählung
wiederdeklariert werden kann, wenn sie einen Enumerator als Namen für Linkage-Zwecke hat
sie kann wiederdeklariert werden
CWG 1884
(P1787R6)
C++98 Die Beschränkungen für mehrere
Deklarationen derselben Entität waren unklar
wurde klargestellt