템플릿 특수화
Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 104개 중 66번째.
때로는 모든 타입에 일반 템플릿이 잘 작동하지 않습니다. 예를 들어, >를 사용하여 C 스타일 문자열을 비교하면 실제 텍스트가 아니라 포인터 주소를 비교합니다. 템플릿 특수화를 사용하면 특정 타입에 맞는 사용자 지정 구현을 제공하면서 다른 모든 경우에는 일반 버전을 유지할 수 있습니다.
전체 특수화는 하나의 특정 타입에 대한 전체 템플릿을 대체합니다. 빈 템플릿 매개변수 목록으로 선언하고 구체적인 타입을 지정합니다:
// 기본 템플릿
template <typename T>
class Printer {
public:
void print(T value) {
std::cout << value << std::endl;
}
};
// const char*에 대한 완전 특수화
template <>
class Printer<const char*> {
public:
void print(const char* value) {
std::cout << "String: " << value << std::endl;
}
};
Printer<int> intPrinter;
intPrinter.print(42); // 출력: 42
Printer<const char*> strPrinter;
strPrinter.print("hello"); // 출력: String: helloFunction 템플릿은 특수화할 수도 있습니다:
template <typename T>
bool isEqual(T a, T b) {
return a == b;
}
template <>
bool isEqual<const char*>(const char* a, const char* b) {
return std::strcmp(a, b) == 0;
}
isEqual(5, 5); // 일반 버전을 사용합니다
isEqual("hi", "hi"); // 특수화된 버전을 사용합니다컴파일러는 항상 가장 구체적인 일치를 우선합니다. 사용 중인 정확한 타입에 대한 특수화가 존재하면 일반 템플릿보다 해당 특수화가 선택됩니다.
챌린지
쉬움특정 타입에 맞게 동작을 사용자 지정하면서도 그 외의 모든 타입에 대해 제네릭 대체 동작을 유지할 수 있도록, 템플릿 특수화의 작동 방식을 보여 주는 타입 인식 포매터 시스템을 만들어 보겠습니다.
템플릿 코드를 구성하기 위해 두 개의 파일을 만듭니다:
Formatter.h: 표시할 값을 형식화하는Formatter라는 클래스 템플릿을 Define합니다. 제네릭 템플릿은 모든 타입에서 작동해야 하지만, 사용자 지정 처리가 필요한 타입을 위한 특수화된 버전도 만듭니다.Primary
Formatter템플릿에는 다음이 있어야 합니다:- 타입 T의 값을 받아
Value: <value>를 출력하는format()method
1 또는 0 대신 사람이 읽을 수 있는 텍스트를 출력하도록
bool에 대한 Full 특수화를 만듭니다:Boolean: true또는Boolean: false를 출력하는format()method
문자열 양쪽에 따옴표를 추가하도록
const char*에 대한 Full 특수화를 만듭니다:String: "<value>"를 출력하는format()method
또한 같은 타입의 두 값을 받아 다음과 같이 함께 출력하는
formatPair라는 function template을 만듭니다:Pair: [<first>, <second>]각 문자열을 따옴표로 감싸도록
const char*에 대한formatPair특수화도 만듭니다:Pair: ["<first>", "<second>"]- 타입 T의 값을 받아
main.cpp: 네 개의 입력을 읽습니다(각각 별도의 줄에 입력):- 정수
- double
- 문자열로 입력된 Boolean (
true또는false) - 문자열 값
적절한
Formatter객체를 만들고 각 타입에 대해format()을 호출하여 포매터를 사용해 봅니다:Formatter<int>를 사용하여 정수를 형식화Formatter<double>를 사용하여 double을 형식화Formatter<bool>를 사용하여 Boolean을 형식화(먼저 문자열 입력을 bool로 Convert)Formatter<const char*>를 사용하여 문자열을 형식화
그런 다음 function template 특수화를 사용해 봅니다:
- 두 정수 10과 20을 사용하여
formatPair호출 - 두 C-문자열
"hello"및"world"를 사용하여formatPair호출
예를 들어 입력이 42, 3.14, true, Hello인 경우:
Value: 42
Value: 3.14
Boolean: true
String: "Hello"
Pair: [10, 20]
Pair: ["hello", "world"]제네릭 템플릿은 정수와 double을 동일한 방식으로 처리하는 반면, bool 및 const char*에 대한 특수화된 버전은 사용자 지정 형식을 제공한다는 점에 주목하세요. 컴파일러는 사용하는 각 타입에 대해 가장 구체적으로 일치하는 항목을 자동으로 선택합니다.
직접 해보기
#include <iostream>
#include <string>
#include "Formatter.h"
using namespace std;
int main() {
// 입력 읽기
int intVal;
double doubleVal;
string boolStr;
string strVal;
cin >> intVal;
cin >> doubleVal;
cin >> boolStr;
cin >> strVal;
// 문자열을 bool로 변환
bool boolVal = (boolStr == "true");
// TODO: Formatter<int>를 생성하고 정수를 포맷하세요
// TODO: Formatter<double>를 생성하고 double을 포맷하세요
// TODO: Formatter<bool>를 생성하고 불리언을 포맷하세요
// TODO: Formatter<const char*>를 생성하고 문자열을 포맷하세요
// Hint: const char*를 얻으려면 strVal.c_str()를 사용하세요
// TODO: 두 정수 10과 20으로 formatPair를 호출하세요
// TODO: 두 C-문자열 "hello"와 "world"로 formatPair를 호출하세요
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 C++ 컴파일러