2009-07-10 6 views
6

C++에서 클래스 및 함수 정의를 익명 네임 스페이스 내에 래핑하여 내부 연결을 지정합니다. 명시 적으로 템플릿을 인스턴스화 할 수도 있지만 템플릿의 명시적인 인스턴스화를 따르는 표준이 동일한 네임 스페이스에서 발생해야합니다. AFAICT이 컴파일해야하지만, GCC는 실패 : 오류로익명 네임 스페이스가 모든 네임 스페이스를 포함합니까?

namespace foo { 

template<class T> 
class bar {}; 

} 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace 'foo') 

익명 네임 스페이스 그냥 정말 네임 스페이스 역할을, 연결을 지정해야하기 때문에 재미있다, 그리고 전역 네임 스페이스는 모든 네임 스페이스를 둘러싸 기 때문에 foo를 확실히 묶습니다. 그러나 심지어이 작동하지 않습니다! :

template<class T> 
class bar {}; 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

단지 대신 글로벌 네임 스페이스를 나열 같은 오류와 함께 실패 어떤 :

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace '::') 

:/

+0

어떤 버전의 GCC - 또는 어떤 컴파일러 옵션 - 또는 어떤 플랫폼입니까? MacOS X에서 G ++ 4.0.1을 사용하는 첫 번째 샘플을 -Wall을 포함하거나 포함하지 않고 시도해 보았습니다. 불만이나 경고없이 컴파일되었습니다. –

+0

Solaris의 GCC 4.2 –

답변

10

익명의 네임 스페이스는 익명의 이름 공간

namespace _TU_specific_unique_generated_name 
{ 
    // ... 
} 
using namespace _TU_specific_unique_generated_name; 

논리적으로 동등하거나, 회원의 링크에 영향을주지 않습니다. 특히 익명 네임 스페이스의 멤버는 마술처럼 내부 연결을 얻지 않습니다.

+1

_TU_specific_unique_generated_name의 내용은 파일 외부에서 사용할 수 없다는 점을 분명히 추가 할 것입니다. – Valentein

+0

실제로 표준에서이 정확한 방법으로 설명되어 있습니다. –

6

당신이 답을 가지고 있다고 생각 - 익명 네임 스페이스는 고유 한 고유 네임 스페이스입니다. BTW, 컴파일러는 내부적으로 해당 네임 스페이스를 나타 내기 위해 임의의 큰 정수를 생성합니다.

0

Stroustrup (섹션 8.2.5.1)에 따르면 전역 네임 스페이스는 익명 (이름이없는) 네임 스페이스에 액세스 할 수 있지만 명시 적으로 그 반대는 아닙니다. 나는 당신이 사용하는 문으로 네임 스페이스를 지정하거나 완전히 익명의 네임 스페이스 내에서 다른 네임 스페이스에 대한 참조를 한정해야 할 것 기대

...

7

첫째, 당신은 명시 적으로 클래스 템플릿을 인스턴스화하는, 당신은 정의되지 않습니다 새로운 클래스 템플릿. 무엇

template class bar<int>; 

는 "여기에 int 유형의 클래스 템플릿 막대를 인스턴스화하십시오."라고되어 있습니다. 다른 네임 스페이스에서 부분적으로 클래스 템플릿을 전문화 할 수없는 것과 마찬가지로 다른 네임 스페이스에서 그렇게 할 수 없습니다. 특히 명시 적으로 인스턴스화 할 템플리트가 정의되어 있어야하며, 예에서 (익명 네임 스페이스) :: bar <>은 foo :: bar <> 만 있습니다.

두 번째 : 익명 네임 스페이스는 실제 네임 스페이스입니다 (단, 모든 번역 단위에서 고유합니다). 그것은 또한 마술처럼 연결을 바꾸지 않습니다. 네임 스페이스 {} 내부에 선언 된 모든 것은 다른 네임 스페이스 범위와 마찬가지로 여전히 기본 연결을 유지합니다. IIRC는 번역 단위 - 사설, 외부 - 연결 개체를 허용하기 위해 추가되었습니다.

관련 문제