C++ CTAD | "클래스 템플릿 인자 추론" 가이드
이 글의 핵심
C++ CTAD에 대한 실전 가이드입니다.
들어가며
C++17에서 도입된 CTAD(Class Template Argument Deduction)는 클래스 템플릿 인자를 자동으로 추론하여 코드를 간결하게 만들어줍니다.
1. CTAD 기본
C++14 vs C++17
// C++14: 타입 명시
std::pair<int, double> p(1, 3.14);
std::vector<int> vec = {1, 2, 3};
// C++17: 타입 추론
std::pair p(1, 3.14);
std::vector vec = {1, 2, 3};
표준 라이브러리
#include <vector>
#include <map>
#include <tuple>
#include <array>
int main() {
std::pair p(1, "Hello");
std::tuple t(1, 2.0, "Hi");
std::vector vec = {1, 2, 3};
std::map m = {{"a", 1}, {"b", 2}};
}
2. 커스텀 클래스 CTAD
기본 예제
#include <iostream>
template<typename T>
class Container {
T value;
public:
Container(T v) : value(v) {}
T get() const { return value; }
};
int main() {
Container c(42);
Container c2(3.14);
Container c3("Hello");
std::cout << c.get() << std::endl; // 42
std::cout << c2.get() << std::endl; // 3.14
std::cout << c3.get() << std::endl; // Hello
}
복사 생성자
#include <iostream>
template<typename T>
class Wrapper {
T value;
public:
Wrapper(T v) : value(v) {}
Wrapper(const Wrapper& other) : value(other.value) {}
T get() const { return value; }
};
int main() {
Wrapper w1(42);
Wrapper w2 = w1;
std::cout << w2.get() << std::endl; // 42
}
3. 추론 가이드 (Deduction Guides)
기본 추론 가이드
#include <iostream>
template<typename T>
class MyClass {
T value;
public:
MyClass(T v) : value(v) {}
};
template<typename T>
MyClass(T) -> MyClass<T>;
int main() {
MyClass obj(42);
std::cout << "OK" << std::endl;
}
커스텀 추론 가이드
#include <iostream>
#include <string>
template<typename T>
class Container {
T value;
public:
Container(T v) : value(v) {}
T get() const { return value; }
};
Container(const char*) -> Container<std::string>;
int main() {
Container c("Hello");
std::cout << c.get() << std::endl; // Hello
}
복잡한 추론 가이드
#include <iostream>
#include <vector>
template<typename T>
class Matrix {
std::vector<std::vector<T>> data;
public:
Matrix(std::vector<std::vector<T>> d) : data(d) {}
};
template<typename T>
Matrix(std::vector<std::vector<T>>) -> Matrix<T>;
int main() {
Matrix m({{1, 2}, {3, 4}});
std::cout << "OK" << std::endl;
}
4. 자주 발생하는 문제
문제 1: 모호한 추론
#include <iostream>
template<typename T>
class Container {
public:
Container(T value) {
std::cout << "T value" << std::endl;
}
Container(T* ptr, size_t size) {
std::cout << "T* ptr" << std::endl;
}
};
int main() {
int arr[5];
Container<int> c(arr, 5);
}
문제 2: 초기화 리스트
#include <vector>
#include <iostream>
int main() {
std::vector vec{1, 2, 3};
std::vector vec2{vec};
std::cout << vec2.size() << std::endl; // 1
std::vector vec3(vec);
std::cout << vec3.size() << std::endl; // 3
}
문제 3: const char*
#include <utility>
#include <string>
#include <iostream>
int main() {
std::pair p("Hello", "World");
std::pair<std::string, std::string> p2("Hello", "World");
std::cout << p2.first << std::endl; // Hello
}
5. 추론 비활성화
explicit 생성자
#include <iostream>
template<typename T>
class NoDeduction {
public:
explicit NoDeduction(T value) {}
};
int main() {
NoDeduction<int> obj(42);
}
6. 실전 예제
예제 1: 스마트 포인터
#include <memory>
#include <iostream>
template<typename T>
class SmartPtr {
T* ptr;
public:
SmartPtr(T* p) : ptr(p) {}
~SmartPtr() { delete ptr; }
T& operator*() { return *ptr; }
};
template<typename T>
SmartPtr(T*) -> SmartPtr<T>;
int main() {
SmartPtr p(new int(42));
std::cout << *p << std::endl; // 42
}
예제 2: 타입 안전 ID
#include <iostream>
#include <string>
template<typename T>
class TypedId {
std::string id;
public:
TypedId(std::string i) : id(i) {}
std::string get() const { return id; }
};
template<typename T>
TypedId(std::string) -> TypedId<T>;
struct User {};
struct Post {};
int main() {
TypedId<User> userId("U001");
TypedId<Post> postId("P001");
std::cout << userId.get() << std::endl; // U001
}
정리
핵심 요약
- CTAD: C++17 클래스 템플릿 인자 추론
- 추론 가이드: 커스텀 추론 규칙
- 표준 라이브러리: pair, vector, map 등
- 성능: 컴파일 타임, 런타임 오버헤드 없음
CTAD 장단점
| 장점 | 단점 |
|---|---|
| 간결한 코드 | 타입 명확성 감소 |
| 타입 안전 | 모호한 추론 가능 |
| 컴파일 타임 | C++17 이상 필요 |
실전 팁
- 타입이 명확할 때 CTAD 사용
- 모호한 경우 명시적 타입 지정
- 추론 가이드로 커스터마이징
const char*는std::string으로 변환 고려
다음 단계
- C++ Deduction Guides
- C++ if constexpr
- C++ Template
관련 글
- C++ 템플릿 인자 추론 | template argument deduction 가이드