Conflicting declarations
달리 명시되지 않는 한, 두 선언은 동일한 개체를 (재)도입할 수 없습니다. 이러한 선언이 존재하는 경우 프로그램은 형식이 잘못되었습니다.
목차 |
해당 선언
두 선언은 다음의 경우를 제외하고 동일한 이름을 (재)도입하거나, 둘 다 생성자를 선언하거나, 둘 다 소멸자를 선언할 때 일치합니다(correspond) .
- 하나는 using 선언 이거나,
- 하나는 타입을 선언하고( typedef 이름 이 아님) 다른 하나는 변수, 익명 공용체 가 아닌 비정적 데이터 멤버, 열거자, 함수, 또는 함수 템플릿을 선언하거나,
- 각각 함수 또는 함수 템플릿을 선언하고 이들이 해당 오버로드를 선언하지 않는 경우.
해당 함수 오버로드
두 개의 function declarations 은 다음의 모든 조건을 충족하는 함수를 선언할 경우 해당 오버로드들 을 선언한다고 합니다:
- 그들은 동일한 parameter-type-list 를 가지며, explicit object parameters 의 타입은 생략합니다 (since C++23) .
|
(C++20부터) |
- 둘 다 비정적 멤버 함수인 경우, 다음 요구 사항 중 하나를 추가로 충족해야 합니다:
|
(C++23부터) |
-
- 해당 객체 매개변수들은 동일한 타입을 가집니다.
대응하는 함수 템플릿 오버로드
두 개의 함수 템플릿 선언 은 다음의 모든 조건을 만족하는 함수 템플릿을 선언할 경우 상응하는 오버로드 를 선언합니다:
- 템플릿 매개변수 목록의 길이가 동일합니다.
- 상응하는 템플릿 매개변수들이 동등합니다 .
- 동등한 매개변수-타입-목록 을 가지며, 명시적 객체 매개변수 의 타입은 제외합니다 (C++23부터) .
- 동등한 반환 타입을 가집니다.
|
(C++20부터) |
- 둘 다 비정적 멤버 함수 템플릿인 경우, 다음 요구 사항 중 하나를 추가로 충족해야 합니다:
|
(C++23부터) |
-
- 해당 객체 매개변수들은 동등한 타입을 가집니다.
struct A { friend void c(); // #1 }; struct B { friend void c() {} // #1에 해당하며 정의함 }; typedef int Int; enum E : int { a }; void f(int); // #2 void f(Int) {} // #2를 정의함 void f(E) {} // OK, 다른 오버로드 struct X { static void f(); void f() const; // 오류: 재선언 void g(); void g() const; // OK void g() &; // 오류: 재선언 void h(this X&, int); void h(int) &&; // OK, 다른 오버로드 void j(this const X&); void j() const &; // 오류: 재선언 void k(); void k(this X&); // 오류: 재선언 };
동일한 엔티티의 다중 선언
|
선언은 그 이름이 _ 인 경우 이름 독립적 이며, 다음을 선언합니다:
|
(C++26부터) |
달리 명시되지 않는 한, 두 엔티티 선언은 다음의 모든 조건이 충족될 경우 동일한 엔티티를 선언합니다 : 이름 없는 타입의 선언이 링크 목적을 위한 typedef 이름 과 열거형 이름 을 도입하는 것으로 간주합니다 (존재하는 경우):
- 이들은 서로 대응됩니다.
- 이들은 동일한 대상 범위 를 가지며, 이 범위는 함수 매개변수 범위 나 템플릿 매개변수 범위 가 아닙니다.
|
(since C++26) |
- 다음 조건 중 하나가 충족됩니다:
-
- 동일한 번역 단위 내에 나타납니다.
|
(C++20부터) |
-
- 둘 다 external linkage 를 가진 이름을 선언합니다.
엔티티 또는 typedef 이름
X
의 선언은, 만약
X
의 다른 선언이 해당 선언으로부터 도달 가능하다면, 그것은
X
의
재선언(redeclaration)
입니다. 그렇지 않다면, 그것은
X
의
최초 선언(first declaration)
입니다.
제한 사항
어떤 엔티티
E
의 두 선언이 아래 해당 제한을 위반하는 경우, 프로그램은 ill-formed입니다:
-
한쪽에서
E를 변수로 선언하면, 다른 쪽에서도E를 동일한 타입의 변수로 선언해야 합니다. -
한쪽에서
E를 함수 로 선언하면, 다른 쪽에서도E를 동일한 타입의 함수로 선언해야 합니다. -
한쪽에서
E를 열거자 로 선언하면, 다른 쪽에서도E를 열거자로 선언해야 합니다. -
한쪽에서
E를 네임스페이스 로 선언하면, 다른 쪽에서도E를 네임스페이스로 선언해야 합니다. -
한쪽에서
E를 클래스 타입 으로 선언하면, 다른 쪽에서도E를 클래스 타입으로 선언해야 합니다. -
한쪽에서
E를 열거형 타입 으로 선언하면, 다른 쪽에서도E를 열거형 타입으로 선언해야 합니다. -
한쪽에서
E를 클래스 템플릿 으로 선언하면, 다른 쪽에서도E를 동등한 템플릿 매개변수 목록을 가진 클래스 템플릿으로 선언해야 합니다( 함수 템플릿 오버로딩 참조). -
한쪽에서
E를 함수 템플릿 으로 선언하면, 다른 쪽에서도E를 동등한 템플릿 매개변수 목록과 타입을 가진 함수 템플릿으로 선언해야 합니다.
|
(C++11부터) |
|
(C++14부터) |
|
(C++20부터) |
타입은 모든 타입 조정 후에 비교됩니다(이 과정에서 typedefs 는 해당 정의로 대체됩니다). 배열 객체에 대한 선언은 주요 배열 경계의 존재 여부에 따라 다른 배열 타입을 지정할 수 있습니다. 두 선언이 서로 도달 가능하지 않은 경우 진단이 요구되지 않습니다.
void g(); // #1 void g(int); // OK, #1과 다른 엔티티 (서로 대응되지 않음) int g(); // 오류: #1과 동일한 엔티티이지만 다른 타입 void h(); // #2 namespace h {} // 오류: #2와 동일한 엔티티이지만 함수가 아님
내부 연결성(internal linkage)을 가진 이름을 선언하는 선언문
H
가 다른 번역 단위(translation unit)
U
에 있는 선언문
D
앞에 위치하고,
H
가
U
에 나타났을 때
D
와 동일한 개체(entity)를 선언하게 된다면, 해당 프로그램은 형식에 맞지 않습니다(ill-formed).
잠재적으로 충돌하는 선언
두 선언은 잠재적으로 충돌할 수 있습니다 만약 이들이 서로 대응하지만 다른 개체를 선언하는 경우.
어떤 범위에서든 이름이 두 선언
A
와
B
에 바인딩되고 이들이 잠재적으로 충돌하는 경우
,
B
가 이름 독립적이지 않으며
(C++26부터)
,
A
가
B
보다 앞선다면, 프로그램의 형식이 올바르지 않습니다:
void f() { int x, y; void x(); // 오류: x에 대한 다른 엔티티 int y; // 오류: 재정의 } enum { f }; // 오류: ::f에 대한 다른 엔티티 namespace A {} namespace B = A; namespace B = A; // OK, 효과 없음 namespace B = B; // OK, 효과 없음 namespace A = B; // OK, 효과 없음 namespace B {} // 오류: B에 대한 다른 엔티티 void g() { int _; _ = 0; // OK int _; // C++26부터 OK, 이름 독립 선언 _ = 0; // 오류: 조회 집합에 두 개의 비함수 선언 존재 } void h () { int _; // #1 _ ++; // OK static int _; // 오류: #1과 충돌 (정적 변수는 이름 독립적이지 않음) // }
결함 보고서
다음 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
|
CWG 279
( P1787R6 ) |
C++98 |
연결 목적을 위한 typedef 이름을 가진 이름 없는 클래스나 열거형을
재선언할 수 있는지 여부가 불분명했음 |
재선언 가능함 |
|
CWG 338
( P1787R6 ) |
C++98 |
연결 목적을 위한 이름으로 열거자를 가진 이름 없는 열거형을
재선언할 수 있는지 여부가 불분명했음 |
재선언 가능함 |
|
CWG 1884
( P1787R6 ) |
C++98 |
동일한 엔티티의 다중 선언에 적용되는
제한 사항이 불분명했음 |
명확히 규정됨 |