Extending the namespace
std
목차 |
std
에 선언 추가하기
std
네임스페이스나
std
내부에 중첩된 어떤 네임스페이스에도 선언이나 정의를 추가하는 것은 미정의 동작입니다. 아래에 명시된 몇 가지 예외를 제외하고.
#include <utility> namespace std { // std 네임스페이스에 추가된 함수 정의: 정의되지 않은 동작 pair<int, int> operator+(pair<int, int> a, pair<int, int> b) { return {a.first + b.first, a.second + b.second}; } }
템플릿 특수화 추가하기
클래스 템플릿
표준 라이브러리 클래스 템플릿에 대한 템플릿 특수화를
std
네임스페이스에 추가하는 것이 허용됩니다. 단, 선언이 적어도 하나의
프로그램 정의 타입
에 의존하고, 해당 특수화가 원본 템플릿의 모든 요구사항을 만족하는 경우에 한합니다. 단, 이러한 특수화가 명시적으로 금지된 경우는 예외입니다.
// 기본 std::hash 템플릿의 선언을 가져옵니다. // 우리는 이를 직접 선언할 수 없습니다. // <typeindex>는 이러한 선언을 제공함이 보장되며, // <functional>을 포함하는 것보다 훨씬 비용이 적게 듭니다. #include <typeindex> // MyType이 std::unordered_set과 std::unordered_map에서 키로 사용될 수 있도록 // std::hash를 특수화합니다. std 네임스페이스를 열면 // 의도치 않게 정의되지 않은 동작을 초래할 수 있으며, // 클래스 템플릿을 특수화하는 데 필요하지 않습니다. template<> struct std::hash<MyType> { std::size_t operator()(const MyType& t) const { return t.hash(); } };
- 템플릿 std::complex 를 float , double , 그리고 long double 이외의 타입에 대해 특수화하는 것은 명시되지 않았습니다.
- std::numeric_limits 의 특수화는 기본 템플릿에서 선언된 모든 멤버들을 static const (until C++11) static constexpr (since C++11) 로 정의해야 하며, 이러한 멤버들이 integral constant expressions 로 사용 가능하도록 해야 합니다.
|
(C++11부터) |
|
(C++17까지) |
표준 라이브러리 클래스 또는 클래스 템플릿의 멤버 클래스 템플릿에 대한 완전 특수화 또는 부분 특수화를 선언하는 것은 정의되지 않은 동작입니다.
|
이 섹션은 불완전합니다
이유: mini-example |
함수 템플릿과 템플릿의 멤버 함수
|
|
(C++20 이전) |
|
표준 라이브러리 함수 템플릿의 완전 특수화를 선언하는 것은 정의되지 않은 동작입니다. |
(C++20 이후) |
|
이 섹션은 불완전합니다
이유: mini-example |
표준 라이브러리 클래스 템플릿의 어떤 멤버 함수에 대한 완전 특수화를 선언하는 것은 정의되지 않은 동작입니다:
|
이 섹션은 불완전합니다
이유: 미니 예시 |
표준 라이브러리 클래스 또는 클래스 템플릿의 멤버 함수 템플릿 전체 특수화를 선언하는 것은 정의되지 않은 동작입니다:
|
이 섹션은 불완전합니다
이유: 미니 예시 |
변수 템플릿
|
명시적으로 허용된 경우를 제외하고, 모든 표준 라이브러리 변수 템플릿의 완전 특수화 또는 부분 특수화를 선언하는 것은 정의되지 않은 행동입니다.
|
(C++14부터) |
템플릿의 명시적 인스턴스화
표준 라이브러리에 정의된 class (since C++20) 템플릿을 명시적으로 인스턴스화하는 것은 선언이 최소한 하나의 program-defined type 이름에 의존하고, 해당 인스턴스화가 원본 템플릿에 대한 표준 라이브러리 요구 사항을 충족하는 경우에만 허용됩니다.
|
이 섹션은 불완전합니다
이유: mini-example |
기타 제한 사항
네임스페이스
std
는
인라인 네임스페이스
로 선언될 수 없습니다.
주소 지정 제한C++ 프로그램이 표준 라이브러리 함수나 표준 라이브러리 함수 템플릿의 인스턴스에 대한 포인터, 참조(자유 함수와 정적 멤버 함수의 경우) 또는 멤버 포인터(비정적 멤버 함수의 경우)를 명시적 또는 암시적으로 생성하려 시도할 경우, 그 동작은 명시되지 않으며(잘못된 형식일 수도 있음) 주소 지정 가능 함수 (아래 참조)로 지정된 경우를 제외하고는 허용되지 않습니다. 다음 코드는 C++17에서는 올바르게 정의되었지만, C++20부터는 명시되지 않은 동작을 초래하며 컴파일되지 않을 수 있습니다: #include <cmath> #include <memory> int main() { // 단항 연산자 & 사용 auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf); // std::addressof 사용 auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf)); // 함수-포인터 암시적 변환 사용 auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf); // 참조 생성 auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf); } 지정된 주소 지정 가능 함수
|
(C++20부터) |
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 120 | C++98 |
사용자가 비사용자 정의 타입에 대해 표준 라이브러리
템플릿을 명시적으로 인스턴스화할 수 있었음 |
금지됨 |
| LWG 232 | C++98 |
선언이 외부 링크를 가진 사용자 정의 이름에 의존하는 경우
(비사용자 정의 타입을 참조할 수 있음) 사용자가 표준 라이브러리 템플릿을 명시적으로 특수화할 수 있었음 |
사용자 정의 타입에 대해서만
허용됨 |
| LWG 422 | C++98 |
사용자가 전체 표준 라이브러리 클래스나 클래스 템플릿을
특수화하지 않고도 개별 멤버나 멤버 템플릿을 특수화할 수 있었음 |
이 경우 동작은
정의되지 않음 |