extending_std — std 네임스페이스 확장

extending_std — std 네임스페이스 확장 (Extending the namespace std)

**std 네임스페이스에 선언을 추가하는 것은 정의되지 않은 동작(undefined behavior)**이에요 — 몇 가지 예외를 제외하고는, std나 그 안에 중첩된 어떤 네임스페이스에 선언이나 정의를 추가하면 안 돼요.

출처: cppreference

본문

std에 선언 추가 (Adding declarations to std)

std에 선언이나 정의를 추가하는 것은 다음 예외를 제외하고 정의되지 않은 동작이에요.

  • 표준 템플릿의 **특수화(specialization)**는, 그 선언이 적어도 하나의 **프로그램 정의 타입(program-defined type)**에 의존하고, 특수화가 원래 템플릿의 모든 요구사항을 만족한다면, std에 추가할 수 있어요 — 단 그런 특수화가 금지된 경우는 제외해요.
#include <functional>

// std::hash를 사용자 타입에 대해 특수화하는 것은 허용
struct MyType { int id; };
namespace std {
    template<>
    struct hash<MyType> {
        std::size_t operator()(const MyType& m) const {
            return std::hash<int>()(m.id);
        }
    };
}

주의할 점들:

  • float, double, long double 이외의 타입에 대한 std::complex 특수화는 **불명시(unspecified)**예요.
  • std::numeric_limits의 특수화는 static constexpr 멤버를 모두 정의해야 해요.
  • std::hash는 사용자 타입에 대해서 특수화할 수 있어요 (위 예).
  • <bits/...> 같은 구현 내부 헤더 접근은 금지돼요.

금지되는 것

  • std새로운 함수, 변수, 클래스, typedef, 변수 템플릿을 추가하는 것 — UB
  • 표준 라이브러리의 기존 선언을 재정의하는 것 — UB
  • std 안에 중첩된 네임스페이스에 아무거나 추가하는 것 — UB
// 금지 — UB
// namespace std { int my_var; }   // 안 됨
// void std::free_func();          // 안 됨

다만 사용자 코드가 std::literals 같은 리터럴 접미사std::literals 안에 추가하는 것은 예외적으로 허용돼요.

// 허용 (C++): 리터럴 연산자 추가
namespace std::literals {
    inline constexpr long double operator""_deg(long double x) { return x; }
}

std를 확장하는 규칙을 지키면 표준 라이브러리를 안전하게 사용자 타입에 맞출 수 있어요. 특히 std::hashstd::numeric_limits 특수화는 자주 쓰이는 허용된 확장이에요.

더 알아보기 (Learn more)

cppreference