부분 템플릿 전문화
Partial template specialization부분 템플릿 지정은 클래스 템플릿 지정의 특정 형식입니다.보통 C++ 프로그래밍 언어와 관련하여 사용되며, 프로그래머는 모든 템플릿 인수가 제공되는 명시적인 완전 전문화와는 대조적으로 클래스 템플릿의 일부 인수만 전문화할 수 있습니다.
템플릿 및 전문화
클래스 템플릿은 실제로 메타 클래스입니다.컴파일러에 적절한 데이터 멤버로 클래스를 만드는 방법에 대한 지침을 제공하는 부분 추상 데이터 유형입니다.예를 들어 C++ 표준 컨테이너는 클래스 템플릿입니다.프로그래머가 벡터를 사용할 경우 특정 데이터 유형(예: int, string 또는 double)으로 인스턴스화합니다.각 유형의 벡터는 컴파일러의 오브젝트 코드에서 다른 클래스를 생성하며 각각 다른 데이터 타입으로 동작합니다.이 과정을 제네릭스의 일원화라고 한다.
클래스 템플릿이 특정 데이터 타입에 꽤 자주 사용되는 것을 알고 있으며, 이 데이터 타입에 따라 최적화(예를 들어 2로 곱하거나 나누는 것이 아니라 정수로 비트 시프트)가 가능한 경우 템플릿 파라미터 중 일부를 미리 설정한 특수 클래스 템플릿을 도입할 수 있습니다.컴파일러는 이러한 클래스 템플릿이 코드로 인스턴스화된 것을 보면 일반적으로 인스턴스화와 일치하는 가장 특수한 템플릿 정의를 선택합니다.따라서 모든 템플릿인수가 일치하는 경우 부분적인 지정보다 명시적인 완전 지정(모든 템플릿인수가 지정됨)이 우선됩니다.
부분적 전문화
템플릿에는 여러 매개 변수 유형을 사용할 수 있습니다.일부 오래된 컴파일러에서는 템플릿의 파라미터를 모두 지정하거나 아예 지정하지 않을 수 있습니다.부분 전문화를 지원하는 컴파일러를 사용하면 프로그래머는 일부 매개변수를 전문화하고 다른 매개변수는 일반 매개변수로 남길 수 있습니다.
예
가 존재한다고 가정합니다.KeyValuePair
클래스에는 다음과 같이 2개의 템플릿 파라미터가 있습니다.
템플릿 < >타이프네임 열쇠, 타이프네임 가치> 학급 키 밸류 페어 {};
다음으로 명시적인 풀템플릿 특화를 정의하는 클래스의 예를 나타냅니다.KeyValuePair
정수를 문자열과 조합하여 사용합니다.클래스 유형은 원래 버전과 동일한 이름을 유지합니다.
템플릿 << 고객명 >>님 학급 키 밸류 페어< >인트, 표준::스트링> {};
다음은 의 부분적인 전문화의 예입니다.KeyValuePair
원래 버전과 이름이 같고 전용 템플릿 매개 변수가 하나 있습니다.
템플릿 < >타이프네임 열쇠> 학급 키 밸류 페어< >열쇠, 표준::스트링> {};
다음 예제 클래스KeyStringPair
원본에서 파생된KeyValuePair
는 새로운 이름을 사용하여 템플릿의 일부 특화를 정의합니다.위의 명시적 특수화와는 달리 슈퍼클래스의 Value template 파라미터만 특수화되며 Key template 파라미터는 범용으로 유지됩니다.
템플릿 < >타이프네임 열쇠> 학급 키 스트링 페어 : 일반의 키 밸류 페어< >열쇠, 표준::스트링> {};
어떤 템플릿파라미터가 특수하고 어떤 템플릿파라미터가 범용적인지는 중요하지 않습니다.예를 들어, 다음은 원본의 부분적인 전문화의 유효한 예이기도 하다.KeyValuePair
학급.
템플릿 < >타이프네임 가치> 학급 Integer Value Pair(정수값 쌍) : 일반의 키 밸류 페어< >인트, 가치> {};
주의사항
C++ 템플릿은 클래스에 한정되지 않으며 함수 템플릿을 정의하는 데도 사용할 수 있습니다.함수 템플릿은 완전히 특수화할 수 있지만 멤버 함수 템플릿인지 비멤버 함수 템플릿인지에 관계없이 부분적으로 특수화할 수 없습니다.이는 컴파일러 라이터에게 유익할 수 있지만 개발자가 수행할 [1]수 있는 작업의 유연성과 세분성에는 영향을 미칩니다.그러나 함수 템플릿이 과부하될 수 있으므로 부분 함수 템플릿의 전문화와 [2]거의 동일한 효과를 얻을 수 있습니다.이러한 점을 설명하기 위해 다음 예를 제시하겠습니다.
// 합법: 기본 함수 템플릿 템플릿 < >타이프네임 반품 타입, 타이프네임 논쟁유형> 반품 타입 푸우(논쟁유형 arg); // 합법: 명시적/완전 함수 템플릿 전문화 템플릿 << 고객명 >>님 표준::스트링 푸우< >표준::스트링, 차>(차 arg) { 돌아가다 "풀"; } // 부적합: 반환 유형의 부분 함수 템플릿 특수화 // 함수 템플릿 부분 지정은 허용되지 않습니다. // template <typename 인수>유형> // 무효 Foo <void, 인수유형>(인수)arg)를 입력합니다. // legal: 포인터 인수 유형의 기본 템플릿을 오버로드합니다. 템플릿 < >타이프네임 반품 타입, 타이프네임 논쟁유형> 반품 타입 푸우(논쟁유형 *argPtr) { 돌아가다 "PtrOverload"; } // 합법: 기본 함수 이름이 재사용되었습니다.과부하로 간주되지 않습니다.잘못된 형식: 선언을 변경할 수 없습니다(아래 참조). 템플릿 < >타이프네임 논쟁유형> 표준::스트링 푸우(논쟁유형 arg) { 돌아가다 "반환 1"; } // 합법: 기본 함수 이름이 재사용되었습니다.과부하로 간주되지 않습니다.잘못된 형식: 선언을 변경할 수 없습니다(아래 참조). 템플릿 < >타이프네임 반품 타입> 반품 타입 푸우(차 arg) { 돌아가다 "반품2'; }
위의 예에서는 함수의 마지막 두 정의가Foo
는 합법적 C++이며, 이들은 오버로드할 수 없는 [3]선언이기 때문에 표준에 따라 잘못된 형식으로 간주됩니다.이는 함수 오버로드의 정의가 함수 이름, 매개 변수 유형 목록 및 둘러싸인 네임스페이스(있는 경우)에 대해서만 설명되기 때문입니다.반환 [4]유형은 고려되지 않습니다.다만, 이러한 함수는, 다음의 프로그램에서 나타내듯이, 컴파일러에의 시그니처를 명시적으로 나타내어 호출할 수 있습니다.
// 참고: 위의 Foo 정의와 함께 컴파일됩니다. 인트 주된(인트 argc, 차 *argv[]) { 차 c = 'c'; 표준::스트링 r0, r1, r2, r3; // 컴파일러가 콜을 해결합니다. r0 = 푸우(c); // 호출할 함수를 명시적으로 지정합니다. r1 = 푸우< >표준::스트링>(c); r2 = 푸우< >표준::스트링, 차>(c); r3 = 푸우< >표준::스트링, 차>(&c); // 출력 생성 표준::외치다 << > r0 << > " " << > r1 << > " " << > r2 << > " " << > r3 << > 표준::끝; 돌아가다 0; } //예상 출력: 반품 1 반품2 가득한 PtrOverload(PtrOverload)
레퍼런스
- ^ Alexandrescu, Andrei (1 February 2001). Modern C++ Design. Addison Wesley. p. 23. ISBN 0-201-70431-5.
- ^ Sutter, Herb (July 2001). "Why Not Specialize Function Templates?". C/C++ Users Journal. 19 (7). Retrieved 7 December 2014.
- ^ "ISO/IEC JTC1 SC22 WG21 N 3690: Programming Languages — C++" (PDF). ISO. 15 May 2013. p. 294. Retrieved 16 October 2016.
13.1 Overloadable declarations [over.load] Not all function declarations can be overloaded. Those that cannot be overloaded are specified here. A program is ill-formed if it contains two such non-overloadable declarations in the same scope.
- ^ "ISO/IEC JTC1 SC22 WG21 N 3690: Programming Languages — C++" (PDF). ISO. 15 May 2013. pp. 294–296. Retrieved 16 October 2016.
13.1 Overloadable declarations [over.load]