Namespaces
Variants

Namespaces

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Namespace declaration
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

네임스페이스는 대규모 프로젝트에서 이름 충돌을 방지하는 방법을 제공합니다.

네임스페이스 블록 내부에 선언된 엔티티들은 네임스페이스 스코프에 배치되며, 이는 다른 스코프에서 동일한 이름을 가진 엔티티들과 혼동되는 것을 방지합니다.

모든 네임스페이스 블록 외부에서 선언된 엔티티는 전역 네임스페이스 에 속합니다. 전역 네임스페이스는 전역 범위 에 속하며, 앞에 :: 를 붙여 명시적으로 참조할 수 있습니다. 선언문이 없지만 전역 네임스페이스는 무명 네임스페이스 가 아닙니다.

동일한 이름을 가진 여러 개의 네임스페이스 블록이 허용됩니다. 이러한 블록 내의 모든 선언은 동일한 네임스페이스 범위에서 선언됩니다.

목차

구문

namespace ns-name { declarations } (1)
inline namespace ns-name { declarations } (2) (C++11부터)
namespace { declarations } (3)
ns-name :: member-name (4)
using namespace ns-name ; (5)
using ns-name :: member-name ; (6)
namespace name = qualified-namespace ; (7)
namespace ns-name :: member-name { declarations } (8) (C++17부터)
namespace ns-name :: inline member-name { declarations } (9) (C++20부터)
1) 명명된 네임스페이스 정의 for the namespace ns-name .
2) 인라인 네임스페이스 정의 for the namespace ns-name . ns-name 내부의 선언들은 이를 감싸는 네임스페이스에서 보이게 됩니다.
3) 이름 없는 네임스페이스 정의 . 해당 멤버들은 선언 지점부터 번역 단위의 끝까지 잠재적 범위를 가지며, 내부 연결 을 가집니다.
4) 네임스페이스 이름(클래스 이름과 함께)은 qualified name lookup 의 일부로서, 범위 지정 연산자의 왼쪽에 나타날 수 있습니다.
5) using-directive : using-directive 이후의 모든 이름에 대한 비한정 name lookup 관점에서, using-directive가 나타나는 지점부터 해당 스코프의 끝까지, ns-name 에 있는 모든 이름은 using-directive와 ns-name 를 모두 포함하는 가장 가까운 둘러싸는 네임스페이스에 선언된 것처럼 보입니다.
6) using-declaration : 네임스페이스 ns-name 에서 심볼 member-name 을 가져와서, 이 using-declaration이 나타나는 동일한 클래스 범위, 블록 범위 또는 네임스페이스에서 선언된 것처럼 unqualified lookup 으로 접근 가능하게 만듭니다.
7) namespace-alias-definition : name 을 다른 네임스페이스의 동의어로 만듭니다: namespace alias 참조
8) 중첩 네임스페이스 정의: namespace A :: B :: C { ... } 는 다음 코드와 동일합니다 namespace A { namespace B { namespace C { ... } } } .
9) 중첩된 인라인 네임스페이스 정의: namespace A :: B :: inline C { ... } 는 다음 코드와 동등합니다: namespace A :: B { inline namespace C { ... } } . inline 은 첫 번째 네임스페이스를 제외한 모든 네임스페이스 이름 앞에 나타날 수 있습니다: namespace A :: inline B :: C { } 는 다음 코드와 동등합니다: namespace A { inline namespace B { namespace C { } } } .

설명

네임스페이스

inline (선택적) namespace attr  (선택적) identifier { namespace-body }
inline - (C++11부터) 존재할 경우 이 네임스페이스를 인라인 네임스페이스로 만듭니다 (아래 참조). original-namespace-definition 에서 inline 을 사용하지 않았다면 extension-namespace-definition 에 나타날 수 없습니다.
attr - (C++17부터) 임의의 개수의 속성 들의 선택적 시퀀스
identifier - 다음 중 하나:
  • 이전에 사용되지 않은 식별자일 경우, 이것은 original-namespace-definition 입니다;
  • 네임스페이스의 이름일 경우, 이것은 extension-namespace-definition 입니다;
  • :: 로 구분된 둘러싸는 네임스페이스 지정자들의 시퀀스로, identifier 로 끝나는 경우, 이것은 nested-namespace-definition 입니다
(C++17부터)
namespace-body - 모든 종류의 선언 들의 가능적으로 빈 시퀀스 (클래스 및 함수 정의와 중첩 네임스페이스 포함)

네임스페이스 정의는 전역 스코프를 포함한 네임스페이스 스코프에서만 허용됩니다.

기존 네임스페이스를 다시 열기 위해서(공식적으로 extension-namespace-definition 이 되기 위해서), 네임스페이스 정의에 사용된 identifier 에 대한 조회는 둘러싸는 네임스페이스 또는 둘러싸는 네임스페이스 내의 인라인 네임스페이스의 멤버로 선언된 네임스페이스 이름(네임스페이스 별칭이 아님)으로 해결되어야 합니다.

namespace-body namespace scope 를 정의하며, 이는 name lookup 에 영향을 미칩니다.

namespace-body 내에 나타나는 선언들에 의해 도입된 모든 이름들 (중첩된 네임스페이스 정의를 포함하여)은 identifier 네임스페이스의 멤버가 됩니다. 이 네임스페이스 정의가 identifier 를 도입한 원래 네임스페이스 정의이든, 이미 정의된 네임스페이스를 "다시 열은" 확장 네임스페이스 정의이든 상관없습니다.

네임스페이스 본문 내에서 선언된 네임스페이스 멤버는 명시적 한정을 사용하여 외부에서 정의되거나 재선언될 수 있습니다

namespace Q
{
    namespace V   // V는 Q의 멤버이며, Q 내부에서 완전히 정의됨
    { // namespace Q::V { // 위 라인들에 대한 C++17 대체 구문
        class C { void m(); }; // C는 V의 멤버이며 V 내부에서 완전히 정의됨
                               // C::m은 선언만 됨
        void f(); // f는 V의 멤버이지만 여기서는 선언만 됨
    }
    void V::f() // V의 멤버 f를 V 외부에서 정의
                // f의 둘러싼 네임스페이스는 여전히 전역 네임스페이스, Q, Q::V임
    {
        extern void h(); // 이는 ::Q::V::h를 선언함
    }
    void V::C::m() // V::C::m을 네임스페이스(및 클래스 본체) 외부에서 정의
                   // 둘러싼 네임스페이스는 전역 네임스페이스, Q, Q::V임
    {}
}

네임스페이스 외부 정의와 재선언은 오직 허용됩니다

  • 선언 지점 이후,
  • 네임스페이스 범위에서, 그리고
  • 원본 네임스페이스를 포함하는 네임스페이스(전역 네임스페이스 포함)에서.

또한, 반드시 정규화된 식별자 구문을 사용해야 합니다.

namespace Q
{
    namespace V    // V에 대한 원래 네임스페이스 정의
    {
        void f();  // Q::V::f 선언
    }
    void V::f() {} // 정상
    void V::g() {} // 오류: g()는 아직 V의 멤버가 아님
    namespace V    // V에 대한 확장 네임스페이스 정의
    {
        void g();  // Q::V::g 선언
    }
}
namespace R           // Q를 포함하는 네임스페이스가 아님
{
    void Q::V::g() {} // 오류: R 내부에서 Q::V::g를 정의할 수 없음
}
void Q::V::g() {}     // 정상: 전역 네임스페이스가 Q를 포함함

비-지역 클래스 X 내부의 friend 선언으로 도입된 이름들은 X의 가장 안쪽에 둘러싸인 네임스페이스의 멤버가 되지만, 일반적인 name lookup ( unqualified qualified 모두)에서는 보이지 않습니다. 단, 네임스페이스 범위에서 클래스 정의 전이나 후에 일치하는 선언이 제공되는 경우는 예외입니다. 이러한 이름은 네임스페이스와 클래스 모두를 고려하는 ADL 을 통해 찾을 수 있습니다.

이러한 friend 선언이 이전에 선언된 이름과 충돌하는지 여부를 결정할 때는 가장 안쪽에 둘러싸는 네임스페이스만 고려됩니다.

void h(int);
namespace A
{
    class X
    {
        friend void f(X);       // A::f는 friend 함수입니다
        class Y
        {
            friend void g();    // A::g는 friend 함수입니다
            friend void h(int); // A::h는 friend 함수이며, ::h와 충돌하지 않습니다
        };
    };
    // A::f, A::g, A::h는 네임스페이스 범위에서 보이지 않습니다
    // 비록 이들이 네임스페이스 A의 멤버일지라도
    X x;
    void g()  // A::g의 정의
    {
        f(x); // ADL을 통해 A::X::f를 찾습니다
    }
    void f(X) {}   // A::f의 정의
    void h(int) {} // A::h의 정의
    // A::f, A::g, A::h는 이제 네임스페이스 범위에서 보입니다
    // 또한 이들은 A::X와 A::X::Y의 friend 함수입니다
}

인라인 네임스페이스(Inline namespaces)

인라인 네임스페이스는 original-namespace-definition 에서 선택적 키워드 inline 을 사용하는 네임스페이스입니다.

인라인 네임스페이스의 멤버는 많은 상황에서(아래 목록) 이를 감싸는 네임스페이스의 멤버인 것처럼 취급됩니다. 이 속성은 전이적입니다: 네임스페이스 N이 인라인 네임스페이스 M을 포함하고, M이 다시 인라인 네임스페이스 O를 포함한다면, O의 멤버는 M이나 N의 멤버인 것처럼 사용될 수 있습니다.

  • 인라인 네임스페이스를 명명하는 using-directive 는 이를 감싸는 네임스페이스에 암시적으로 삽입됩니다(이름 없는 네임스페이스에 대한 암시적 using-directive와 유사함)
  • 인수 종속 lookup(argument-dependent lookup) 에서 네임스페이스가 연관 네임스페이스 집합에 추가될 때, 그 인라인 네임스페이스들도 함께 추가됩니다. 그리고 인라인 네임스페이스가 연관 네임스페이스 목록에 추가되면, 이를 감싸는 네임스페이스도 추가됩니다.
  • 인라인 네임스페이스의 각 멤버는 이를 감싸는 네임스페이스의 멤버인 것처럼 부분 특수화(partially specialized), 명시적 인스턴스화(explicitly instantiated), 또는 명시적 특수화(explicitly specialized)될 수 있습니다.
  • 이를 감싸는 네임스페이스를 검사하는 한정된 이름 lookup(name lookup) 은 동일한 이름이 감싸는 네임스페이스에 존재하더라도 인라인 네임스페이스들의 이름들을 포함합니다.
// in C++14, std::literals and its member namespaces are inline
{
    using namespace std::string_literals; // makes visible operator""s 
                                          // from std::literals::string_literals
    auto str = "abc"s;
{
    using namespace std::literals; // makes visible both
                                   // std::literals::string_literals::operator""s
                                   // and std::literals::chrono_literals::operator""s
    auto str = "abc"s;
    auto min = 60s;
{
    using std::operator""s; // makes both std::literals::string_literals::operator""s
                            // and std::literals::chrono_literals::operator""s visible
    auto str = "abc"s;
    auto min = 60s;
}

참고: 특수화에 대한 규칙은 라이브러리 버전 관리를 허용합니다: 라이브러리 템플릿의 서로 다른 구현들을 서로 다른 인라인 네임스페이스에 정의할 수 있으면서, 사용자가 기본 템플릿의 명시적 특수화(explicit specialization)로 부모 네임스페이스를 확장하는 것을 여전히 허용합니다:

namespace Lib
{
    inline namespace Lib_1
    {
        template<typename T> class A; 
    }
    template<typename T> void g(T) { /* ... */ }
}
/* ... */
struct MyClass { /* ... */ };
namespace Lib
{
    template<> class A<MyClass> { /* ... */ };
}
int main()
{
    Lib::A<MyClass> a;
    g(a);  // ok, Lib is an associated namespace of A
}
(C++11부터)

이름 없는 네임스페이스

unnamed-namespace-definition 은 다음과 같은 형태의 네임스페이스 정의입니다

inline (선택적) namespace attr  (선택적) { namespace-body }
inline - (since C++11) 존재할 경우, 이 네임스페이스를 인라인 네임스페이스로 만듭니다
attr - (since C++17) 임의의 개수의 속성 에 대한 선택적 시퀀스

이 정의는 고유한 이름을 가진 네임스페이스의 정의와 이 무명 네임스페이스를 현재 범위에서 지정하는 using-directive 로 처리됩니다 (참고: 암시적으로 추가된 using 지시문은 qualified name lookup unqualified name lookup 에는 네임스페이스를 사용 가능하게 하지만, argument-dependent lookup 에는 사용 가능하게 하지 않습니다). 고유한 이름은 전체 프로그램에서 고유하지만, 하나의 번역 단위 내에서는 각 무명 네임스페이스 정의가 동일한 고유 이름에 매핑됩니다: 동일한 범위에서의 여러 무명 네임스페이스 정의는 동일한 무명 네임스페이스를 나타냅니다.

namespace
{
    int i; // defines ::(unique)::i
}
void f()
{
    i++;   // increments ::(unique)::i
}
namespace A
{
    namespace
    {
        int i;        // A::(unique)::i
        int j;        // A::(unique)::j
    }
    void g() { i++; } // A::(unique)::i++
}
using namespace A; // introduces all names from A into global namespace
void h()
{
    i++;    // error: ::(unique)::i and ::A::(unique)::i are both in scope
    A::i++; // ok, increments ::A::(unique)::i
    j++;    // ok, increments ::A::(unique)::j
}

이름 없는 네임스페이스 내의 이름들이 외부 링크age로 선언될 수 있지만, 그 네임스페이스 이름이 고유하기 때문에 다른 번역 단위에서 접근할 수 없습니다.

(until C++11)

이름 없는 네임스페이스와 이름 없는 네임스페이스 내에서 직접 또는 간접적으로 선언된 모든 네임스페이스는 내부 링크age 를 가지며, 이는 이름 없는 네임스페이스 내에서 선언된 모든 이름이 내부 링크age를 가짐을 의미합니다.

(since C++11)

using 선언

이 using 선언이 나타나는 선언 영역으로 다른 곳에서 정의된 이름을 도입합니다.

using typename (선택 사항) nested-name-specifier unqualified-id ; (C++17 이전)
using declarator-list ; (C++17 이후)
typename - typename 키워드는 using 선언이 클래스 템플릿에 베이스 클래스의 멤버 타입을 도입할 때 종속 이름(dependent names) 을 해결하기 위해 필요에 따라 사용될 수 있음
nested-name-specifier - 이름과 범위 지정 연산자 :: 의 시퀀스로, 범위 지정 연산자로 끝남. 단일 :: 는 전역 네임스페이스를 참조함
unqualified-id - 식별자 표현(id-expression)
declarator-list - 하나 이상의 선언자(declarator)를 쉼표로 구분한 목록으로, 형식은 typename (선택사항) nested-name-specifier unqualified-id 임. 선언자 뒤에는 팩 확장(pack expansion) 을 나타내는 줄임표가 올 수 있으나, 이 형태는 파생 클래스 정의(derived class definitions) 에서만 의미가 있음

using 선언은 네임스페이스 멤버를 다른 네임스페이스와 블록 범위로 도입하거나, 기본 클래스 멤버를 파생 클래스 정의로 도입하는 데 사용할 수 있습니다 , 또는 enumerators 를 네임스페이스, 블록, 클래스 범위로 도입하는 데 사용할 수 있습니다 (since C++20) .

둘 이상의 using-선언자를 가진 using-선언은 하나의 using-선언자를 가진 해당 using-선언 시퀀스와 동등합니다.

(since C++17)

파생 클래스 정의에서의 사용을 위해서는 using 선언 을 참조하십시오.

using 선언에 의해 네임스페이스 범위로 도입된 이름들은 다른 모든 이름들과 마찬가지로 사용될 수 있으며, 여기에는 다른 범위들로부터의 한정된 조회도 포함됩니다:

void f();
namespace A
{
    void g();
}
namespace X
{
    using ::f;        // 전역 f가 이제 ::X::f로 보임
    using A::g;       // A::g가 이제 ::X::g로 보임
    using A::g, A::g; // (C++17) OK: 네임스페이스 범위에서 중복 선언 허용됨
}
void h()
{
    X::f(); // ::f 호출
    X::g(); // A::g 호출
}

using 선언을 사용하여 네임스페이스로부터 멤버를 가져온 후, 해당 네임스페이스가 확장되어 동일한 이름에 대한 추가 선언이 도입되면, 그 추가 선언들은 using 선언을 통해 보이지 않습니다(using 지시문과 대조적). 한 가지 예외는 using 선언이 클래스 템플릿을 명시할 때입니다: 나중에 도입된 부분 특수화는 실제로 보이는데, 이는 그들의 조회 가 기본 템플릿을 통해 진행되기 때문입니다.

namespace A
{
    void f(int);
}
using A::f; // ::f는 이제 A::f(int)의 동의어입니다
namespace A       // 네임스페이스 확장
{
    void f(char); // ::f의 의미를 변경하지 않습니다
}
void foo()
{
    f('a'); // f(char)가 존재함에도 불구하고 f(int)를 호출합니다
}
void bar()
{
    using A::f; // 이 f는 A::f(int)와 A::f(char) 모두의 동의어입니다
    f('a');     // f(char)를 호출합니다
}

using-선언은 template-id , 또는 네임스페이스 , 또는 범위 열거자 (until C++20) 를 명시할 수 없습니다. using-선언의 각 선언자는 하나의 이름만을 도입하며, 예를 들어 enumeration 에 대한 using-선언은 해당 열거자의 어떤 열거자도 도입하지 않습니다.

같은 이름의 일반 선언에 대한 모든 제한 사항, 숨김 및 오버로딩 규칙은 using 선언에도 적용됩니다:

namespace A
{
    int x;
}
namespace B
{
    int i;
    struct g {};
    struct x {};
    void f(int);
    void f(double);
    void g(char); // OK: 함수 이름 g가 struct g를 숨김
}
void func()
{
    int i;
    using B::i;   // 오류: i가 두 번 선언됨
    void f(char);
    using B::f;   // OK: f(char), f(int), f(double)이 오버로드됨
    f(3.5);       // B::f(double) 호출
    using B::g;
    g('a');       // B::g(char) 호출
    struct g g1;  // g1을 struct B::g 타입으로 선언
    using B::x;
    using A::x;   // OK: struct B::x를 숨김
    x = 99;       // A::x에 할당
    struct x x1;  // x1을 struct B::x 타입으로 선언
}

using 선언으로 도입된 함수와 동일한 이름과 매개변수 목록을 가진 함수를 선언하는 것은 올바르지 않습니다(단, 동일한 함수에 대한 선언인 경우는 제외). using 선언으로 도입된 함수 템플릿과 동일한 이름, 매개변수 타입 목록, 반환 타입, 템플릿 매개변수 목록을 가진 함수 템플릿을 선언하는 것도 올바르지 않습니다. 두 개의 using 선언이 동일한 이름과 매개변수 목록을 가진 함수를 도입할 수 있지만, 해당 함수를 호출하려고 시도하면 프로그램이 올바르지 않게 됩니다.

namespace B
{
    void f(int);
    void f(double);
}
namespace C
{
    void f(int);
    void f(double);
    void f(char);
}
void h()
{
    using B::f;  // B::f(int), B::f(double)를 도입
    using C::f;  // C::f(int), C::f(double), C::f(char)를 도입
    f('h');      // C::f(char) 호출
    f(1);        // 오류: B::f(int)인가 C::f(int)인가?
    void f(int); // 오류: f(int)가 C::f(int) 및 B::f(int)와 충돌
}

어떤 엔티티가 내부 네임스페이스에서 선언되었지만 정의되지 않고, 이후 using 선언을 통해 외부 네임스페이스에서 선언된 후, 동일한 비한정 이름을 가진 정의가 외부 네임스페이스에 나타나면, 해당 정의는 외부 네임스페이스의 멤버가 되며 using 선언과 충돌합니다:

namespace X
{
    namespace M
    {
        void g(); // 선언하지만 X::M::g()를 정의하지는 않음
    }
    using M::g;
    void g();     // 오류: X::M::g()와 충돌하는 X::g 선언 시도
}

더 일반적으로, 네임스페이스 스코프에 나타나고 비한정 식별자를 사용하여 이름을 도입하는 선언은 항상 해당 이름이 속한 네임스페이스의 멤버를 도입하며 다른 네임스페이스에는 도입하지 않습니다. 예외는 인라인 네임스페이스에 정의된 기본 템플릿의 명시적 인스턴스화와 명시적 특수화입니다: 이들은 새로운 이름을 도입하지 않기 때문에, 둘러싼 네임스페이스에서 비한정-id를 사용할 수 있습니다.

using 지시문

using-directive 는 다음 구문을 가진 block-declaration 입니다:

attr  (선택사항) using namespace nested-name-specifier  (선택사항) namespace-name ; (1)
attr - (since C++11) 이 using-directive에 적용되는 임의 개수의 attributes
nested-name-specifier - 이름과 범위 확인 연산자 :: 의 시퀀스로, 범위 확인 연산자로 끝남. 단일 :: 는 전역 네임스페이스를 참조함. 이 시퀀스의 이름을 조회할 때, lookup 은 네임스페이스 선언만 고려함
namespace-name - 네임스페이스의 이름. 이 이름을 조회할 때, lookup 은 네임스페이스 선언만 고려함

using 지시문은 네임스페이스 scope 와 블록 scope에서만 허용됩니다. using 지시문 이후의 모든 이름에 대한 unqualified name lookup 관점에서, using 지시문이 나타나는 scope의 끝까지, namespace-name 에 있는 모든 이름은 using 지시문과 namespace-name 를 모두 포함하는 가장 가까운 enclosing namespace에 선언된 것처럼 보입니다.

using 지시문은 나타나는 선언 영역에 어떤 이름도 추가하지 않으며(using 선언과 달리), 따라서 동일한 이름의 선언을 방지하지 않습니다.

using-지시문은 비정규화된 이름 검색 의 목적상 전이적입니다: 어떤 범위가 namespace-name 를 지정하는 using-지시문을 포함하고, 이 네임스페이스 자체가 다른 namespace-name-2 에 대한 using-지시문을 포함하는 경우, 두 번째 네임스페이스의 using 지시문들이 첫 번째 네임스페이스 내에 나타나는 것과 같은 효과를 가집니다. 이러한 전이적 네임스페이스들이 나타나는 순서는 이름 검색에 영향을 미치지 않습니다.

namespace A
{
    int i;
}
namespace B
{
    int i;
    int j;
    namespace C
    {
        namespace D
        {
            using namespace A;
            // A의 이름들이 D로 "주입"됩니다
            // D 내부의 비한정 이름 검색은 이러한 이름들을 전역 범위와 동일한
            // 범위를 가진 것으로 간주합니다(예: 이름 숨김 목적을 위해)
            // D를 참조하는 한정 이름 검색(D::name 형태)은
            // D 내부의 비한정 이름 검색과 동일한 이름을 찾습니다
            int j;
            int k;
            int a = i;   // i는 B::i입니다. A::i가 B::i에 의해 숨겨지기 때문입니다
            int b = ::i; // 오류: 전역 네임스페이스에 여전히 i가 없습니다
        }
        using namespace D; // D와 A의 이름들이 C로 주입됩니다
        int k = 89; // using으로 도입된 이름과 동일한 이름 선언 가능
        int l = k;  // 모호함: C::k인가 D::k인가
        int m = i;  // ok: B::i가 A::i를 숨깁니다
        int n = j;  // ok: D::j가 B::j를 숨깁니다
    }
}
// 다음은 모두 동등한 정의들입니다:
int t0 = B::i;
int t1 = B::C::a;
int t2 = B::C::D::a;

using-directive를 사용하여 일부 네임스페이스를 지정한 후, 해당 네임스페이스가 확장되어 추가 멤버 및/또는 using-directive가 추가되면, 그 추가 멤버들과 추가 네임스페이스들은 using-directive를 통해 표시됩니다 (using-declaration과 대조적으로)

namespace D
{
    int d1;
    void f(char);
}
using namespace D; // D::d1, D::f, D::d2, D::f,
                   // E::e, E::f를 전역 네임스페이스로 도입합니다!
int d1;            // OK: 선언 시 D::d1과 충돌하지 않음
namespace E
{
    int e;
    void f(int);
}
namespace D            // 네임스페이스 확장
{
    int d2;
    using namespace E; // 전이적 using 지시문
    void f(int);
}
void f()
{
    d1++;    // 오류: 모호함 ::d1 또는 D::d1?
    ::d1++;  // OK
    D::d1++; // OK
    d2++;    // OK, d2는 D::d2임
    e++;     // OK: e는 전이적 using으로 인해 E::e임
    f(1);    // 오류: 모호함: D::f(int) 또는 E::f(int)?
    f('a');  // OK: 유일한 f(char)는 D::f(char)임
}

참고 사항

using 지시문 using namespace std ; 를 네임스페이스 스코프에서 사용하면 std 네임스페이스의 모든 이름이 전역 네임스페이스로 도입됩니다(전역 네임스페이스는 std 와 사용자 정의 네임스페이스를 모두 포함하는 가장 가까운 네임스페이스이기 때문). 이는 바람직하지 않은 이름 충돌을 일으킬 수 있습니다. 이러한 using 지시문은 일반적으로 헤더 파일의 파일 스코프에서 사용하는 것이 좋지 않은 방법으로 간주됩니다( SF.7: 헤더 파일의 전역 스코프에서 using namespace 을 사용하지 마십시오 ).

기능 테스트 매크로 표준 기능
__cpp_namespace_attributes 201411L (C++17) 속성 네임스페이스용

키워드

namespace , using , inline

예제

이 예제는 이미 std 네임스페이스에 존재하는 클래스 이름을 사용하여 클래스를 생성하는 방법을 보여줍니다.

#include <vector>
namespace vec
{
    template<typename T>
    class vector
    {
        // ...
    };
} // of vec
int main()
{
    std::vector<int> v1; // Standard vector.
    vec::vector<int> v2; // User defined vector.
    // v1 = v2;          // Error: v1 and v2 are different object's type.
    {
        using namespace std;
        vector<int> v3;  // Same as std::vector
        v1 = v3; // OK
    }
    {
        using vec::vector;
        vector<int> v4;  // Same as vec::vector
        v2 = v4; // OK
    }
}

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 101 C++98 네임스페이스 범위나 블록 범위의 함수 선언과 using 선언으로
도입된 함수가 동일한 함수를 선언하면 프로그램이 비형식적임
(모호성 없음)
허용됨
CWG 373 C++98 using 지시문의 피연산자 마지막 이름에 대해서만
네임스페이스 선언을 고려함 (최적이 아님,
클래스는 네임스페이스를 포함할 수 없기 때문)
탐색 제한이 using 지시문의
모든 피연산자 이름에
적용됨
CWG 460 C++98 using 선언이 네임스페이스를 지정할 수 있었음 금지됨
CWG 565 C++98 using 선언이 동일한 범위의 다른 함수와
동일한 함수를 도입할 수 없었지만,
이 제한이 함수 템플릿에는 적용되지 않았음
동일한 제한을 함수 템플릿에도
적용함
CWG 986 C++98 using 지시문이 한정된 탐색에 대해 전이적이었음 비한정 탐색에만 전이적임
CWG 987 C++98 중첩된 네임스페이스에서 선언된 개체들이
둘러싸는 네임스페이스의 멤버이기도 했음
중첩된 범위는 제외됨
CWG 1021 C++98 using 선언을 통해 네임스페이스로 정의가 도입된 개체가
해당 네임스페이스에서 정의된 것으로 간주되는지
명확하지 않았음
해당 네임스페이스에서 정의되지 않음
CWG 1838 C++98 외부 네임스페이스의 비한정 정의가 다른 네임스페이스에서
선언되었지만 정의되지 않은 개체를 using으로 가져와
정의할 수 있었음
비한정 정의는 항상
자신의 네임스페이스를
참조함
CWG 2155 C++98 CWG 이슈 1838 의 해결책이
클래스 및 열거형 선언에 적용되지 않았음
적용됨

참고 항목

namespace alias 기존 네임스페이스의 별칭을 생성합니다