Programming/C++

C++ : 고급 템플릿

나무수피아 2025. 5. 22. 01:15
728x90
반응형

고급 템플릿 프로그래밍

1. SFINAE, enable_if

   SFINAE (Substitution Failure Is Not An Error)는 템플릿 메타프로그래밍에서 중요한 개념으로, 템플릿 인자에 따라 컴파일 타임에 조건을 처리할 수 있도록 합니다. `enable_if`는 특정 조건에 맞는 타입만을 허용하는 데 사용됩니다.

1.1. SFINAE

   템플릿을 사용할 때 조건에 맞지 않으면 컴파일 오류를 발생시키는 대신, 해당 템플릿을 제외시킵니다. 이를 통해 오버로딩을 사용할 때 더욱 유연하게 템플릿을 설계할 수 있습니다.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, T> add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << add(3, 4) << std::endl;  // int형 덧셈
    // std::cout << add(3.14, 2.71) << std::endl;  // 컴파일 오류 (float는 허용되지 않음)
    return 0;
}

1.2. enable_if

`enable_if`는 조건이 만족될 때만 템플릿을 활성화하도록 도와줍니다. 이로 인해 조건에 맞는 타입만을 허용하게 할 수 있습니다.

#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << add(5, 10) << std::endl;  // int형 덧셈
    return 0;
}

2. 템플릿 메타프로그래밍

   템플릿 메타프로그래밍(TMP)은 템플릿을 사용하여 컴파일 타임에 계산을 수행하는 기법입니다. 이를 통해 런타임에 계산을 지연시키거나 최적화할 수 있습니다.

2.1. 컴파일 타임 계산

   템플릿 메타프로그래밍을 사용하면 컴파일 타임에 계산을 수행할 수 있습니다. 예를 들어 팩토리얼 값을 계산하는 템플릿을 만들어 볼 수 있습니다.

#include <iostream>

template <int N>
struct factorial {
    static constexpr int value = N * factorial<N - 1>::value;
};

template <>
struct factorial<0> {
    static constexpr int value = 1;
};

int main() {
    std::cout << factorial<5>::value << std::endl;  // 120
    return 0;
}

3. type_traits, std::variant, std::any

   `type_traits`, `std::variant`, `std::any`는 고급 템플릿 프로그래밍에서 매우 유용한 도구들입니다. `type_traits`는 타입에 대한 정보를 제공하며, `std::variant`와 `std::any`는 타입 안전성을 보장하는 데 유용합니다.

3.1. type_traits

   `type_traits`는 타입에 대한 특성을 컴파일 타임에 검사할 수 있게 해주는 유용한 템플릿 도구입니다. 예를 들어, 타입이 정수형인지 확인할 수 있습니다.

#include <iostream>
#include <type_traits>

template <typename T>
void printIfIntegral(T t) {
    if constexpr (std::is_integral<T>::value) {
        std::cout << t << std::endl;
    } else {
        std::cout << "Not an integral type!" << std::endl;
    }
}

int main() {
    printIfIntegral(42);  // 출력: 42
    printIfIntegral(3.14);  // 출력: Not an integral type!
    return 0;
}

3.2. std::variant

   `std::variant`는 여러 타입을 하나의 변수로 다룰 수 있는 안전한 방법을 제공합니다. `std::variant`는 타입이 확실히 하나일 때만 값을 가지며, 여러 타입을 안전하게 다룰 수 있습니다.

#include <iostream>
#include <variant>

std::variant<int, double, std::string> getData(int choice) {
    if (choice == 0) return 42;
    else if (choice == 1) return 3.14;
    else return "Hello";
}

int main() {
    auto data = getData(1);
    std::visit([](auto&& arg){ std::cout << arg << std::endl; }, data);
    return 0;
}

3.3. std::any

   `std::any`는 어떤 타입이든 저장할 수 있는 컨테이너입니다. 이를 통해 타입을 명시적으로 다루지 않고도 다양한 타입의 값을 저장할 수 있습니다.

#include <iostream>
#include <any>

int main() {
    std::any a = 42;
    std::cout << std::any_cast<int>(a) << std::endl;  // 출력: 42

    a = std::string("Hello, C++!");
    std::cout << std::any_cast<std::string>(a) << std::endl;  // 출력: Hello, C++!
    return 0;
}
728x90
반응형

'Programming > C++' 카테고리의 다른 글

C++ : 전문가 프로젝트  (65) 2025.05.26
C++ : 대규모 프로젝트 아키텍처  (45) 2025.05.25
C++ : 성능 최적화  (82) 2025.05.24
C++ : 스레드와 동기화  (60) 2025.05.23
C++ : 현대적 C++  (76) 2025.05.21
C++ : 스마트 포인터  (94) 2025.05.20
C++ : 고급 객체지향 설계  (94) 2025.05.19
C++ : 중급 프로젝트  (10) 2025.05.18