템플릿(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개의 배열. char
s는 다음과 같이 선언될 수 있습니다.
배열한<촤, 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에서는 컴파일 시 함수를 사용하여 이러한 값을 직접 계산하는 데 사용할 수 있습니다. 이 때문에 템플릿 메타 프로그래밍은 현재 대부분 유형에 대한 작업을 수행하는 데 사용됩니다.
참고 항목
참고문헌
- ^ Stroustrup, Bjarne (8 September 2004). "The C++ Programming Language". Stroustrup.com (personal homepage) (3rd, Special ed.).
- ^ Lippman, Stan (11 August 2004). "Why C++ Supports both Class and Typename for Type Parameters". Microsoft Developers Network (MSDN).
- ^ "P1141R1 - Yet another approach for constrained declarations". Archived from the original on 2018-11-11. Retrieved 2018-11-11.
- ^ Vandevoorde, Daveed; Josuttis, Nicolai (2002). C++ Templates: The Complete Guide. Addison Wesley. ISBN 978-0-201-73484-3.
- ^ "Differences Between C++ Templates and C# Generics (C# Programming Guide)".