C++ CTAD | Class Template Argument Deduction (C++17)
이 글의 핵심
CTAD lets you write `std::vector v = {1,2,3}` and custom types with constructor-driven template argument deduction.
Introduction
CTAD (Class Template Argument Deduction), introduced in C++17, deduces class template arguments from constructor arguments so you can omit explicit template parameters.
1. CTAD basics
C++14 vs C++17
// C++14: explicit types
std::pair<int, double> p(1, 3.14);
std::vector<int> vec = {1, 2, 3};
// C++17: deduced
std::pair p(1, 3.14);
std::vector vec = {1, 2, 3};
Standard library
#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. Custom class CTAD
Basic example
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");
}
Copy construction
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; }
};
3. Deduction guides
Simple guide
template<typename T>
class MyClass {
T value;
public:
MyClass(T v) : value(v) {}
};
template<typename T>
MyClass(T) -> MyClass<T>;
Custom conversions
template<typename T>
class Container {
T value;
public:
Container(T v) : value(v) {}
T get() const { return value; }
};
Container(const char*) -> Container<std::string>;
Iterator / nested types
Guides can map (It, It) to vector<value_type_t<It>>—the standard library does this for several constructors.
4. Common pitfalls
Ambiguous deduction
Multiple constructors can compete; guides disambiguate intent.
initializer_list and CTAD
Brace initialization can prefer initializer_list constructors—sometimes surprising; be explicit when needed.
const char* and std::string
Pairs of string literals may deduce to pair<string,string> if you construct that way explicitly; know your overload set.
5. Disabling deduction
explicit constructors do not participate in implicit copy-list-initialization patterns the same way—use explicit types when you must.
6. Examples: smart pointer–style, typed IDs
The article includes SmartPtr(T*) -> SmartPtr<T> and typed identifier wrappers—same code as the Korean version.
Summary
- CTAD deduces class template parameters from constructors (C++17).
- Deduction guides customize that mapping.
- Standard library types commonly use CTAD.
- Cost: compile-time only; no runtime overhead.
Trade-offs
| Pros | Cons |
|---|---|
| Shorter code | Types can be less visible at a glance |
| Still type-safe | Ambiguity if overloads clash |
| Compile-time | Requires C++17+ |
Tips
- Prefer CTAD when types are obvious.
- Spell out template arguments when readability wins.
- Use guides for conversions like
const char*→std::string.
Related posts
- Deduction guides
if constexpr- Template argument deduction
Keywords
C++, CTAD, class template argument deduction, deduction guide, C++17.