템플릿(C++)

Template (C++)

템플릿C++ 프로그래밍 언어의 기능으로 기능클래스일반 유형으로 작동할 수 있습니다. 따라서 함수 또는 클래스 선언은 이러한 각 다른 클래스에 대한 전체 선언을 만들지 않고 일반 변수를 통해 다른 클래스(빌트인 또는 새로 선언된 데이터 유형)를 참조할 수 있습니다.

C++ 표준 라이브러리는 연결된 템플릿 프레임워크 내에서 많은 유용한 기능을 제공합니다.

C++ 템플릿의 주요 영감은 언어 CLU에서 제공하는 매개 변수화된 모듈과 Ada에서 제공하는 제네릭이었습니다.[1]

기술개요

템플릿에는 함수 템플릿, 클래스 템플릿C++14 이후 변수 템플릿의 세 가지 종류가 있습니다. C++11 이후 템플릿은 변수형이거나 비변수형일 수 있습니다. C++의 이전 버전에서는 항상 비변수형입니다.

함수 템플릿

함수 템플릿은 여러 가지 유형의 인수를 가질 수 있다는 점을 제외하고는 함수처럼 동작합니다(예: 참조). 즉, 함수 템플릿은 함수 계열을 나타냅니다. 유형 매개 변수가 있는 함수 템플릿을 선언하는 형식은 다음과 같습니다.

템플릿<학급 식별자> 선언.; 템플릿<활자명 식별자> 선언.; 

두 표현 모두 같은 의미를 가지며 정확히 같은 방식으로 행동합니다. 후자의 형식은 형식 매개변수가 C++20까지는 클래스일 필요가 [2]없으므로 혼동을 피하기 위해 도입되었습니다. (다음과 같은 기본 형식일 수 있습니다.) int 아니면 double.)

예를 들어, C++ 표준 라이브러리에는 함수 템플릿이 포함되어 있습니다. max(x, y) 더 큰 것을 돌려주는 것입니다. x 그리고. y. 해당 함수 템플릿은 다음과 같이 정의할 수 있습니다.

템플릿<활자명 T> T 맥스.(T &a, T &b) { 돌아가다 a > b ? a : b; } 

이 단일 함수 정의는 많은 데이터 유형과 함께 작동합니다. 특히 >(보다 큰 연산자)가 정의된 모든 데이터 유형에서 작동합니다. 함수 템플릿을 사용하면 소스 코드 파일의 공간을 절약할 수 있을 뿐만 아니라 변경 사항을 하나의 함수 설명으로 제한하고 코드를 쉽게 읽을 수 있습니다.

그러나 템플릿은 특정 프로그램에서 사용되는 모든 다른 데이터 유형에 대해 별도의 기능을 작성하는 것과 비교하여 더 작은 개체 코드를 생성하지 않습니다. 예를 들어, 프로그램이 두 가지를 모두 사용하는 경우 int 그리고 a. double 버전의 max() 위에 표시된 함수 템플릿은 컴파일러가 개체 코드 버전을 만듭니다. max() 에서 작동하는 int 인수 및 다음에서 작동하는 다른 개체 코드 버전 double 논쟁들. 컴파일러 출력은 소스 코드에 두 개의 템플릿이 없는 버전이 포함되어 있었다면 생성되었을 것과 동일할 것입니다. max(), 다루기 위해 쓴 것 int 그리고 하나는 다루기 위해 쓰여진 것입니다. double.

함수 템플릿을 사용할 수 있는 방법은 다음과 같습니다.

# <아이오스트림>  인트의 주된() {     // 이것은 암시적 인수 공제를 통해 max<int>를 호출합니다.     std::꾸트 << 맥스.(3, 7) << '\n'';      // 이것은 암시적 인수 공제를 통해 max<double>을 호출합니다.     std::꾸트 << 맥스.(3.0, 7.0) << '\n'';      // 인수 유형을 명시적으로 지정해야 합니다.      // std::type_identity가 이 문제를 해결할 수 있지만...     std::꾸트 << 맥스.<두 배의>(3, 7.0) << '\n''; } 

처음 두 경우에는 템플릿 인수 T 컴파일러에 의해 자동으로 추론됩니다. int 그리고. double,각각 다음과 같다. 세 번째 경우에는 자동으로 공제됩니다. max(3, 7.0) 매개 변수의 유형이 일반적으로 템플릿 인수와 정확히 일치해야 하므로 실패합니다. 따라서, 우리는 명시적으로 다음을 인스턴스화합니다. double 와 버전. max<double>().

이 함수 템플릿은 식에 대한 복사 구성 가능 유형으로 인스턴스화할 수 있습니다. y > x 유효합니다. 사용자 정의 유형의 경우, 이는 다음 연산자보다 큰 연산자()를 의미합니다.>)을(를) 형식에 오버로드해야 합니다.

축약 함수 템플릿

C++20 이후, 사용 auto 아니면 Concept auto 함수 선언의 매개 변수 중 하나에서, 그 선언은 축약 함수 템플릿 선언이 됩니다.[3] 이러한 선언은 함수 템플릿을 선언하고 각 자리 표시자에 대한 하나의 발명된 템플릿 매개 변수가 템플릿 매개 변수 목록에 추가됩니다.

공허한 f1(오토); // 템플릿과 동일 <클래스 T> 보이드 f1(T) 공허한 f2(C1 오토); // C1이 개념일 경우 템플릿과 동일 <C1 T> void f2(T) 공허한 f3(C2 오토...); // 템플릿과 동일 <C2... C2가 개념일 경우 Ts> void f3(Ts...) 공허한 f4(C2 오토, ...); // C2가 개념일 경우 템플릿 <C2 T> void f4(T...)와 동일합니다. 공허한 f5(상투적인 C3 오토*, C4 오토&); // 템플릿과 동일 <C3 T, C4 U> void f5 (const T*, U&); 

클래스 템플릿

클래스 템플릿은 매개 변수를 기반으로 클래스를 생성하기 위한 규격을 제공합니다. 클래스 템플릿은 일반적으로 컨테이너를 구현하는 데 사용됩니다. 클래스 템플릿은 지정된 유형 집합을 템플릿 인수로 전달하여 인스턴스화됩니다.[4] C++ 표준 라이브러리에는 많은 클래스 템플릿, 특히 다음과 같은 표준 템플릿 라이브러리에서 적용된 컨테이너가 포함되어 있습니다. vector.

변수 템플릿

C++14에서는 다음 예제와 같이 템플릿을 변수에 사용할 수도 있습니다.

템플릿<활자명 T>  정곡을 찌르다 T 파이 = T{3.141592653589793238462643383L}; // (거의) std::numbers::pi에서 

유형이 아닌 템플릿 매개 변수

위의 예제와 같이 유형에 템플릿을 적용하는 것이 C++에서 템플릿을 적용하는 가장 일반적인 형태이지만 값에 템플릿을 적용하는 것도 가능합니다. 따라서, 예를 들어, 클래스는 다음과 같이 선언됩니다.

템플릿 <인트의 K> 학급 마이 클래스; 

특정을 사용하여 인스턴스화할 수 있습니다. int.

실제 예로, 표준 라이브러리 고정 크기 배열 유형 std::array 형식(배열이 보유하는 개체 유형을 나타냄)과 형식이 있는 숫자 모두에 템플릿화됩니다. std::size_t (어레이가 보유한 요소 수를 나타냅니다.) std::array 다음과 같이 선언할 수 있습니다.

템플릿<학급 T, size_t N> 짜임새 있는 배열한; 

그리고 6개의 배열. chars는 다음과 같이 선언될 수 있습니다.

배열한<, 6> 마이어레이; 

템플릿 전문화

템플릿에서 함수 또는 클래스가 인스턴스화되면 사용된 인수 집합에 대해 해당 템플릿의 전문화가 컴파일러에 의해 생성되며, 이 전문화를 생성된 전문화라고 합니다.

명시적 템플릿 전문화

때때로 프로그래머는 명시적 특수화라고 불리는 템플릿 유형 인수의 주어진 집합에 대한 함수(또는 클래스)의 특별한 버전을 구현하기로 결정할 수 있습니다. 이러한 방식으로 특정 템플릿 유형은 유형에 최적화된 특수 구현을 갖거나 일반 구현보다 더 의미 있는 구현을 가질 수 있습니다.

  • 클래스 템플릿이 해당 매개 변수의 하위 집합에 의해 특수화되는 경우 이를 부분 템플릿 특수화(함수 템플릿은 부분 특수화할 수 없음)라고 합니다.
  • 모든 매개변수가 전문화된 경우 전체 전문화입니다.

명시적 특수화는 템플릿 매개 변수의 특정 선택에 대한 함수 또는 클래스의 동작이 일반적인 동작(즉, 주 템플릿 또는 템플릿에 의해 생성된 코드)에서 벗어나야 하는 경우에 사용됩니다. 예를 들어, 아래 템플릿 정의는 다음의 특정 구현을 정의합니다. max() 유형의 논법으로 const char*:

# <cstring>  템플릿<>  상투적인 * 맥스.(상투적인 * a, 상투적인 * b) {     // 일반적으로 직접 비교한 결과     // 두 C 스트링 사이에는 정의되지 않은 동작이 있습니다.     // std::strcmp makes 정의를 사용합니다.     돌아가다 std::strcmp(a, b) > 0 ? a : b; } 

버라이어티 템플릿

C++11은 다음과 같은 변수 함수와 다소 유사한 방식으로 변수 수의 인수를 취할 수 있는 변수 템플릿을 도입했습니다. std::printf.

템플릿 별칭

C++11은 매개변수화된 타입 데프와 같은 역할을 하는 템플릿 별칭을 도입했습니다.

다음 코드는 템플릿 별칭의 정의를 보여줍니다. StrMap. 예를 들어, 이것은 다음과 같이 허용합니다. StrMap<int> 의 약자로 쓰입니다 std::unordered_map<int,std::string>.

템플릿<활자명 T> 사용. StrMap = std::순서 없는_map<T, std::끈의>; 

다른 언어의 일반 프로그래밍 기능

초기에 템플릿의 개념은 자바나 C# 1.0과 같은 일부 언어에 포함되지 않았습니다. 자바의 제네릭 채택은 템플릿의 동작을 모방하지만 기술적으로 다릅니다. C#에서 제네릭(파라미터화된 유형)을 추가했습니다.NET 2.0. Ada의 제네릭은 C++ 템플릿보다 우선합니다.

C++ 템플릿, Java 제네릭 및 .NET 제네릭은 종종 유사한 것으로 간주되며 제네릭은 C++ 템플릿의 기본 동작만 모방합니다.[5] 템플릿 메타프로그래밍을 위해 Boost, STLsoft와 같은 라이브러리와 STL의 구현에서 사용되는 고급 템플릿 기능 중 일부는 일반적인 버전에서는 사용할 수 없습니다.

C++ 템플릿에서 컴파일 시간 사례는 템플릿 인수에 대한 패턴 일치에 의해 역사적으로 수행되었습니다. 예를 들어, 아래 요인 예제의 템플릿 기본 클래스는 이전에는 사용할 수 없었던 부등식 검정이 아니라 0을 일치시켜 구현됩니다. 그러나 std::conditional과 같은 표준 라이브러리 기능이 C++11에 도입되면서 조건부 템플릿 인스턴스화를 처리할 수 있는 또 다른 유연한 방법이 제공되었습니다.

// 인덕션  템플릿<서명이 없는 N>  짜임새 있는 요인 {   정적인 정곡을 찌르다 서명이 없는 가치 = N * 요인<N - 1>::가치; };  // 템플릿 전문화를 통한 기본 케이스:  템플릿<> 짜임새 있는 요인<0> {   정적인 정곡을 찌르다 서명이 없는 가치 = 1; }; 

이 정의를 사용하면 컴파일 시에 6!과 같은 식을 계산할 수 있습니다. Factorial<6>::value. 아니면. constexpr C++11에서 / consteval C++20에서는 컴파일 시 함수를 사용하여 이러한 값을 직접 계산하는 데 사용할 수 있습니다. 이 때문에 템플릿 메타 프로그래밍은 현재 대부분 유형에 대한 작업을 수행하는 데 사용됩니다.

참고 항목

참고문헌

  1. ^ Stroustrup, Bjarne (8 September 2004). "The C++ Programming Language". Stroustrup.com (personal homepage) (3rd, Special ed.).
  2. ^ Lippman, Stan (11 August 2004). "Why C++ Supports both Class and Typename for Type Parameters". Microsoft Developers Network (MSDN).
  3. ^ "P1141R1 - Yet another approach for constrained declarations". Archived from the original on 2018-11-11. Retrieved 2018-11-11.
  4. ^ Vandevoorde, Daveed; Josuttis, Nicolai (2002). C++ Templates: The Complete Guide. Addison Wesley. ISBN 978-0-201-73484-3.
  5. ^ "Differences Between C++ Templates and C# Generics (C# Programming Guide)".

외부 링크