CodeNebula
C++20coreadvanced

Class Template Argument Deduction Enhancements (C++20 Evolution)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

Improved deduction for aggregates and aliases, simplifying instantiation.

Real-World Scenario

Create a pair in a data processor without specifying types.

Quick Snippet

snippet.cpp
std::pair p = {1, "value"}; // Deduced as std::pair<int, std::string>

Full Example

ctad_enhancements.cpp
// CodeNebula - C++20 Example: CTAD Enhancements
// Compile: g++ -std=c++20 -Wall -Wextra -o example ctad_enhancements.cpp

// C++20 enhances Class Template Argument Deduction (CTAD):
//   1. CTAD for aggregates — no deduction guides needed
//   2. CTAD for alias templates — aliases can deduce too
//   3. Improvements to deduction guides

#include <iostream>
#include <vector>
#include <array>
#include <tuple>
#include <string>
#include <functional>
#include <memory>

// --- 1. CTAD for aggregates (C++20) ---
// In C++17, aggregates needed explicit deduction guides.
// C++20 deduces template parameters from aggregate init automatically.

template <typename T, typename U>
struct Pair {
    T first;
    U second;
};

template <typename T>
struct Holder {
    T value;
    int count;
};

template <typename T, int N>
struct FixedArray {
    T data[N];
};

// --- 2. CTAD for alias templates (C++20) ---
// Aliases can now participate in CTAD

template <typename T>
using Vec = std::vector<T>;

template <typename T>
using MyPair = Pair<T, T>;  // alias restricts both to same type

// --- 3. A class with custom deduction guide ---
template <typename T>
struct Wrapper {
    T value;

    Wrapper(T v) : value(v) {}
    Wrapper(T v, int) : value(v) {}  // second overload
};

// Deduction guide: const char* -> std::string
Wrapper(const char*) -> Wrapper<std::string>;

// --- Helper printer ---
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const Pair<T, U>& p) {
    return os << "{" << p.first << ", " << p.second << "}";
}

int main() {
    std::cout << "=== C++20 CTAD Enhancements ===\n\n";

    // --- Aggregate CTAD ---
    std::cout << "1. CTAD for aggregates:\n";

    // Deduces Pair<int, double>
    Pair p1{42, 3.14};
    std::cout << "   Pair{42, 3.14}       = " << p1 << "\n";

    // Deduces Pair<std::string, int>
    Pair p2{std::string("hello"), 5};
    std::cout << "   Pair{\"hello\", 5}     = " << p2 << "\n";

    // Deduces Holder<double>
    Holder h{2.718, 3};
    std::cout << "   Holder{2.718, 3}      = {" << h.value << ", " << h.count << "}\n";

    std::cout << "\n";

    // --- Alias template CTAD ---
    std::cout << "2. CTAD for alias templates:\n";

    // Vec deduces to std::vector<int>
    Vec v1{1, 2, 3, 4, 5};
    std::cout << "   Vec{1,2,3,4,5}:        ";
    for (int x : v1) std::cout << x << " ";
    std::cout << "\n";

    // MyPair deduces both types as the same
    MyPair mp{10, 20};  // Pair<int, int>
    std::cout << "   MyPair{10, 20}        = " << mp << "\n";

    std::cout << "\n";

    // --- Standard library CTAD improvements ---
    std::cout << "3. Standard library CTAD:\n";

    // std::array CTAD
    std::array arr{1, 2, 3, 4};  // deduces std::array<int, 4>
    std::cout << "   std::array{1,2,3,4}:   ";
    for (int x : arr) std::cout << x << " ";
    std::cout << "(size=" << arr.size() << ")\n";

    // std::tuple CTAD
    std::tuple tup{42, 3.14, std::string("abc")};
    std::cout << "   std::tuple{42,3.14,\"abc\"}: ("
              << std::get<0>(tup) << ", "
              << std::get<1>(tup) << ", "
              << std::get<2>(tup) << ")\n";

    // std::pair CTAD
    std::pair sp{100, "text"};
    std::cout << "   std::pair{100,\"text\"}: ("
              << sp.first << ", " << sp.second << ")\n";

    std::cout << "\n";

    // --- Custom deduction guide ---
    std::cout << "4. Custom deduction guides:\n";

    Wrapper w1{42};          // Wrapper<int>
    Wrapper w2{"hello"};     // Wrapper<std::string> via deduction guide
    std::cout << "   Wrapper{42}:      " << w1.value << "\n";
    std::cout << "   Wrapper{\"hello\"}: " << w2.value << "\n";

    return 0;
}

// Expected output:
// === C++20 CTAD Enhancements ===
//
// 1. CTAD for aggregates:
//    Pair{42, 3.14}       = {42, 3.14}
//    Pair{"hello", 5}     = {hello, 5}
//    Holder{2.718, 3}      = {2.718, 3}
//
// 2. CTAD for alias templates:
//    Vec{1,2,3,4,5}:        1 2 3 4 5
//    MyPair{10, 20}        = {10, 20}
//
// 3. Standard library CTAD:
//    std::array{1,2,3,4}:   1 2 3 4 (size=4)
//    std::tuple{42,3.14,"abc"}: (42, 3.14, abc)
//    std::pair{100,"text"}: (100, text)
//
// 4. Custom deduction guides:
//    Wrapper{42}:      42
//    Wrapper{"hello"}: hello
Run command
g++ -std=c++20 -Wall -Wextra -o example ctad_enhancements.cpp