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::hash와 std::numeric_limits 특수화는 자주 쓰이는 허용된 확장이에요.