[2026] C++ CTAD | Class Template Argument Deduction (C++17)

[2026] C++ CTAD | Class Template Argument Deduction (C++17)

이 글의 핵심

Learn C++17 CTAD: omit template arguments for `pair`, `vector`, and custom types. Deduction guides, `explicit` constructors, and common pitfalls with `initializer_list`.

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

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// 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

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#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

다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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

아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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

아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

template<typename T>
class MyClass {
    T value;
    
public:
    MyClass(T v) : value(v) {}
};
template<typename T>
MyClass(T) -> MyClass<T>;

Custom conversions

아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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

  1. CTAD deduces class template parameters from constructors (C++17).
  2. Deduction guides customize that mapping.
  3. Standard library types commonly use CTAD.
  4. Cost: compile-time only; no runtime overhead.

Trade-offs

ProsCons
Shorter codeTypes can be less visible at a glance
Still type-safeAmbiguity if overloads clash
Compile-timeRequires 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.

Keywords

C++, CTAD, class template argument deduction, deduction guide, C++17.

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3