Skip to content

네임스페이스

namespace는 함수와 전역 변수를 한정된(qualified) 이름 아래로 묶는다. C++의 namespace 문법과 일치한다. 이 기능이 존재하는 주된 이유는 표준 라이브러리가 내부 헬퍼 함수들이 사용자 코드의 동일한 이름의 식별자와 충돌하지 않으면서도, 자신의 전체 표면을 std:: 아래로 노출할 수 있게 하기 위해서다.

c
namespace std {
    int square(int x) { return x * x; }
    int counter = 41;

    namespace inner {
        int triple(int x) { return x * 3; }
    }
}

int main(void) {
    int a = std::square(6);          // 한정된 접근
    int b = std::inner::triple(4);   // 중첩된 네임스페이스, 한정된 접근
    std::counter = std::counter + 1;

    int c = square(6);               // 한정 없는 접근도 폴백으로 동작
    return 0;
}

네임스페이스가 적용되는 대상

함수와 전역 변수만 네임스페이스가 적용된다. 구조체, 열거형, typedef 이름은 의도적으로 네임스페이스 대상에서 제외된다 — 모든 타입 이름은 어느 namespace { } 블록 안에 선언되었든 상관없이 하나의 평평한 전역 네임스페이스에 존재한다. 이는 실수가 아니라 의도적인 스코프 설계다: SafeC의 C ABI 호환성은 구조체 이름이 곧 툴링과 FFI를 위한 맹글링된 심볼 정체성이기도 하다는 것을 의미하며, C에는 네임스페이스가 적용된 타입이라는 개념 자체가 없다 — 타입을 평평하게 유지함으로써 C 쪽에 대응물이 전혀 없는 맹글링 스킴을 새로 만들어내는 일을 피한다.

c
namespace net {
    struct Packet { int len; };   // 'struct Packet'은 전역이며 net::Packet이 아니다
}

struct Packet p;   // 동작함 -- 'net::' 한정자가 필요하지도, 허용되지도 않음

한정된 조회 대 한정 없는 조회

같은 네임스페이스 안(또는 어떤 네임스페이스도 열지 않은 코드)에서의 호출은 전체 한정 경로를 통해서든 그냥 이름만으로든 네임스페이스가 적용된 함수나 변수에 도달할 수 있다 — 한정 없는 조회는 평범한 스코프에 일치하는 것이 없을 때 네임스페이스가 적용된 심볼을 검색하는 것으로 폴백된다. 이것이 표준 라이브러리 코드는 자신의 헬퍼를 한정 없이 호출할 수 있는 반면, 사용자 코드는 보통 std::something 형태로 호출하는 이유다.

링키지

네임스페이스가 적용된 함수나 변수는 단일한 맹글링된 심볼로 컴파일된다 (std::foostd_foo) — 네임스페이스는 순전히 소스 레벨의 한정/조회 메커니즘일 뿐, 런타임 구성물이 아니다. 네임스페이스 메타데이터도, ABI에 노출되는 네임스페이스 태그도 없으며, 맹글링된 이름 자체 외에는 아무것도 존재하지 않는다. namespace { } 블록 안의 extern 선언은 유일한 예외다 — extern은 애초에 사전에 존재하는 외부 심볼에 정확한, 맹글링되지 않은 이름으로 바인딩하기 위해 존재하므로(예: namespace std { } 안의 extern void* memcpy(...)는 libc와 링크하기 위해 그냥 memcpy 그대로 유지되어야 한다), extern 선언은 어떤 네임스페이스로 감싸여 있든 상관없이 절대 맹글링되지 않는다. 메서드(Type::method(...)) 역시 마찬가지로 제외된다 — 이들은 이미 자신만의 methodOwner로 한정된 메커니즘을 통해 디스패치되므로, 이중으로 맹글링하는 것은 불필요한 중복이다.

MIT 라이선스로 배포됩니다.