본문으로 건너뛰기 C++ CTAD | Class Template Argument Deduction (C++17)

C++ CTAD | Class Template Argument Deduction (C++17)

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

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

  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.


Frequently Asked Questions (FAQ)

Q. When would I use this in practice?

A. Learn C++17 CTAD: omit template arguments for pair, vector, and custom types.

Q. What should I read before this?

A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the C++ series index for the full picture.

Q. Where can I study this more deeply?

A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.


Other articles related to this topic.


Keywords Covered in This Article (Related Search Terms)

This article covers C++, CTAD, Templates, C++17, Deduction.