2015-01-15 1 views
2

다음 코드는 (적어도 GCC의 최신 버전에 대한) 컴파일 오류가 발생합니다 :친구 선언에서 정규화 된 이름을 사용하기위한 규칙은 무엇입니까?

namespace a { 

class X { friend void ::foo(); }; 

} 

오류는 다음과 같습니다

'void foo()' should have been declared inside '::' 

우리가 표준에 따라, 선언에서 ::을 제거하는 경우 , foo은 (표시되지는 않지만) 네임 스페이스 a에 도입됩니다. foo 내부에있는 foo는 a 일 필요는 없습니다.

내 질문에 위와 같이 전역 네임 스페이스 내에서 미리 선언해야하는 이유는 무엇입니까? foo이라는 이름이 글로벌 네임 스페이스의 구성원이되지 않는 이유는 무엇입니까? 표준에서 명시 적으로 금지하는 단락을 찾을 수 없으므로 궁금합니다.

답변

2

당신이 찾고있는 단락 [dcl.meaning]이다 (8.3 (1) C++ 11에서) :

(...)를 선언자-ID은 규정하지 않는다 클래스 외부에있는 멤버 함수 또는 정적 데이터 멤버의 정의, 네임 스페이스 외부의 네임 스페이스의 함수 또는 변수에 대한 정의 또는 명시 적 인스턴스화, 네임 스페이스 외부의 명시 적 전문화 정의 또는 선언 다른 클래스 또는 네임 스페이스의 멤버 인 friend 함수 선언자 ID가 인 경우, 선언은 한정자가을 가리키는 클래스 또는 네임 스페이스의 이전에 선언 된 멤버를 참조해야합니다 (또는 네임 스페이스의 경우 인라인 네임 스페이스 집합의 요소 집합). 그 네임 스페이스).

(강조 광산) 이것이 의미하는 것은 당신이 a::foo 않는

namespace a { } 

void a::foo() { } 

이미 네임 스페이스 내부 규정 화되지 않은 선언자로 선언 쓸 수 있다는 것입니다. 그리고 친구에게는 예외가 없으므로 친구들에게도 이것을 할 수 없습니다.

[namespace.memdef]에서의 각주 (7.3.1.2 (3) C++ 11에서)이 훨씬 더 명시 적으로 친구의 특별한 경우에 대한 언급

:

(...)를하는 경우 비 로컬 클래스의 friend 선언은 먼저 클래스 또는 함수를 선언합니다. 친구 클래스 또는 함수가 가장 안쪽에있는 네임 스페이스의 멤버입니다. (...)

이는 클래스 또는 기능의 이름이 규정되지 않았 음을 의미합니다.

관련 문제