ν…œν”Œλ¦Ώ 메타 ν”„λ‘œκ·Έλž˜λ°μ˜ λͺ¨λ“  것(Template Meta Programming)

2024. 8. 28. 08:55Β·ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄/C++ μ‘μš©

 

 

ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ° (Template Metaprogramming)

ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°(Template Metaprogramming)은 C++의 κ°•λ ₯ν•œ ν…œν”Œλ¦Ώ μ‹œμŠ€ν…œμ„ μ΄μš©ν•˜μ—¬ 컴파일 νƒ€μž„μ— μ½”λ“œμ˜ 일뢀λ₯Ό μƒμ„±ν•˜κ±°λ‚˜ κ³„μ‚°ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° κΈ°λ²•μž…λ‹ˆλ‹€. 이 기법은 C++의 ν…œν”Œλ¦Ώμ„ λ‹¨μˆœν•œ μ½”λ“œ μž¬μ‚¬μš© λ„κ΅¬λ‘œ μ‚¬μš©ν•˜λŠ” κ²ƒμ—μ„œ 더 λ‚˜μ•„κ°€, λ³΅μž‘ν•œ κ³„μ‚°μ΄λ‚˜ 쑰건 처리λ₯Ό 컴파일 μ‹œμ μ— 미리 μˆ˜ν–‰ν•˜μ—¬, μ‹€ν–‰ μ‹œμ μ˜ μ„±λŠ₯을 κ·ΉλŒ€ν™”ν•  수 있게 ν•©λ‹ˆλ‹€.

1. κΈ°λ³Έ κ°œλ…

ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ€ 일반적인 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œμ˜ μ‹€ν–‰ μ‹œμ (runtime) ν”„λ‘œκ·Έλž˜λ°κ³ΌλŠ” λ‹€λ₯΄κ²Œ, ν”„λ‘œκ·Έλž¨μ΄ 컴파일될 λ•Œ μˆ˜ν–‰λ©λ‹ˆλ‹€. μ΄λŠ” ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜κΈ° 전에 λ‹€μ–‘ν•œ μž‘μ—…μ„ 미리 μˆ˜ν–‰ν•˜μ—¬, μ‹€ν–‰ μ‹œμ μ—μ„œλŠ” μ΅œλŒ€ν•œ 효율적인 μ½”λ“œλ§Œμ„ μ‹€ν–‰ν•  수 μžˆλ„λ‘ ν•˜λŠ” 것을 λͺ©ν‘œλ‘œ ν•©λ‹ˆλ‹€.

μ΄λŸ¬ν•œ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ„ 톡해, μˆ˜ν•™μ  계산, 쑰건 처리, μ½”λ“œ 생성 등을 컴파일 μ‹œμ μ— μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μ£Όμš” νŠΉμ§•:
    • 컴파일 νƒ€μž„ 계산: λ³΅μž‘ν•œ κ³„μ‚°μ΄λ‚˜ 논리λ₯Ό 컴파일 νƒ€μž„μ— μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • μ½”λ“œ 생성: μ‹€ν–‰ μ‹œμ μ— λ™μ μœΌλ‘œ 생성할 ν•„μš” 없이, 컴파일 νƒ€μž„μ— ν•„μš”ν•œ μ½”λ“œλ‚˜ 데이터λ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • μ„±λŠ₯ μ΅œμ ν™”: μ‹€ν–‰ μ‹œμ μ˜ 뢀담을 쀄여 ν”„λ‘œκ·Έλž¨μ˜ μ„±λŠ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
    • μž¬μ‚¬μš©μ„±: ν…œν”Œλ¦Ώμ„ μ΄μš©ν•œ μΌλ°˜ν™”λœ μ½”λ“œλ₯Ό μž‘μ„±ν•¨μœΌλ‘œμ¨, μž¬μ‚¬μš©μ„±κ³Ό ν™•μž₯성을 높일 수 μžˆμŠ΅λ‹ˆλ‹€.


2. 예제 μ½”λ“œμ™€ μ„€λͺ…

예제 1: νŒ©ν† λ¦¬μ–Ό 계산

ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ„ μ‚¬μš©ν•˜μ—¬ νŒ©ν† λ¦¬μ–Όμ„ 컴파일 νƒ€μž„μ— κ³„μ‚°ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

#include <iostream>

// κΈ°λ³Έ ν…œν”Œλ¦Ώ (μž¬κ·€ 호좜)
template<int N>
struct Factorial {
    static constexpr int value = N * Factorial<N - 1>::value;
};

// μž¬κ·€ μ’…λ£Œ 쑰건 (N = 0)
template<>
struct Factorial<0> {
    static constexpr int value = 1;
};

int main() {
    std::cout << "Factorial of 5: " << Factorial<5>::value << std::endl;  // Output: 120
    return 0;
}

μ„€λͺ…:

  • 이 μ˜ˆμ œμ—μ„œ Factorial ꡬ쑰체 ν…œν”Œλ¦Ώμ€ μž¬κ·€μ μœΌλ‘œ νŒ©ν† λ¦¬μ–Όμ„ κ³„μ‚°ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, Factorial<5>λŠ” 5 * Factorial<4>둜 ν™•μž₯λ©λ‹ˆλ‹€.
  • Factorial<0>은 κΈ°λ³Έ 쑰건으둜, μž¬κ·€ ν˜ΈμΆœμ„ μ’…λ£Œν•˜λŠ” 역할을 ν•©λ‹ˆλ‹€.
  • μ΅œμ’…μ μœΌλ‘œ, 컴파일 νƒ€μž„μ— Factorial<5>::valueλŠ” 120으둜 κ³„μ‚°λ©λ‹ˆλ‹€.

예제 2: 컴파일 νƒ€μž„μ—μ„œ 쑰건뢀 νƒ€μž… 선택

ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ„ μ‚¬μš©ν•˜μ—¬ 컴파일 νƒ€μž„μ— 쑰건에 따라 νƒ€μž…μ„ μ„ νƒν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

#include <iostream>
#include <type_traits>

// ν…œν”Œλ¦Ώ 쑰건에 따라 νƒ€μž…μ„ μ„ νƒν•˜λŠ” ꡬ쑰체
template<bool Condition, typename TrueType, typename FalseType>
struct Conditional {
    using type = TrueType;
};

// νŠΉμˆ˜ν™”: 쑰건이 false일 λ•Œ
template<typename TrueType, typename FalseType>
struct Conditional<false, TrueType, FalseType> {
    using type = FalseType;
};

int main() {
    using SelectedType = Conditional<(sizeof(int) > 4), double, int>::type;

    if constexpr (std::is_same_v<SelectedType, double>) {
        std::cout << "Selected type is double." << std::endl;
    } else {
        std::cout << "Selected type is int." << std::endl;
    }

    return 0;
}

μ„€λͺ…:

  • Conditional κ΅¬μ‘°μ²΄λŠ” μ£Όμ–΄μ§„ 쑰건(컴파일 νƒ€μž„ 쑰건)에 따라 TrueType λ˜λŠ” FalseType 쀑 ν•˜λ‚˜λ₯Ό μ„ νƒν•©λ‹ˆλ‹€.
  • 이 μ˜ˆμ œμ—μ„œλŠ” sizeof(int) > 4λΌλŠ” 쑰건을 톡해 SelectedType이 double인지 int인지λ₯Ό κ²°μ •ν•©λ‹ˆλ‹€.
  • if constexpr을 μ‚¬μš©ν•˜μ—¬ μ„ νƒλœ νƒ€μž…μ— 따라 λ‹€λ₯Έ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

예제 3: 컴파일 νƒ€μž„μ—μ„œ 제곱 계산

ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ„ μ‚¬μš©ν•˜μ—¬ 숫자의 μ œκ³±μ„ 컴파일 νƒ€μž„μ— κ³„μ‚°ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

#include <iostream>

// κΈ°λ³Έ ν…œν”Œλ¦Ώ (μž¬κ·€ 호좜)
template<int N, int Power>
struct PowerOf {
    static constexpr int value = N * PowerOf<N, Power - 1>::value;
};

// μž¬κ·€ μ’…λ£Œ 쑰건 (Power = 0)
template<int N>
struct PowerOf<N, 0> {
    static constexpr int value = 1;
};

int main() {
    std::cout << "2^4: " << PowerOf<2, 4>::value << std::endl;  // Output: 16
    return 0;
}

μ„€λͺ…:

  • PowerOf ꡬ쑰체 ν…œν”Œλ¦Ώμ€ μž¬κ·€μ μœΌλ‘œ 숫자의 μ œκ³±μ„ κ³„μ‚°ν•©λ‹ˆλ‹€.
  • PowerOf<N, 0>은 κΈ°λ³Έ 쑰건으둜, μž¬κ·€ ν˜ΈμΆœμ„ μ’…λ£Œν•˜λŠ” 역할을 ν•©λ‹ˆλ‹€.
  • 컴파일 νƒ€μž„μ— PowerOf<2, 4>::valueλŠ” 16으둜 κ³„μ‚°λ©λ‹ˆλ‹€.


3. ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ˜ μž₯단점

μž₯점:

  • 컴파일 νƒ€μž„ μ΅œμ ν™”: λ³΅μž‘ν•œ 계산을 μ‹€ν–‰ μ‹œμ μ΄ μ•„λ‹Œ 컴파일 μ‹œμ μ— μˆ˜ν–‰ν•  수 μžˆμ–΄ μ„±λŠ₯이 ν–₯μƒλ©λ‹ˆλ‹€.
  • νƒ€μž… μ•ˆμ „μ„±: ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ€ κ°•λ ₯ν•œ νƒ€μž… 검사λ₯Ό μ œκ³΅ν•˜μ—¬, μ½”λ“œμ˜ μ•ˆμ „μ„±μ„ λ†’μž…λ‹ˆλ‹€.
  • μ½”λ“œ μž¬μ‚¬μš©μ„±: μΌλ°˜ν™”λœ μ½”λ“œλ₯Ό μž‘μ„±ν•  수 μžˆμ–΄, λ‹€μ–‘ν•œ 상황에 맞게 μž¬μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

단점:

  • λ³΅μž‘μ„±: ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ€ 맀우 λ³΅μž‘ν•  수 있으며, μ΄ν•΄ν•˜κΈ° μ–΄λ €μš΄ μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό μ΄ˆλž˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 컴파일 μ‹œκ°„ 증가: λ³΅μž‘ν•œ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ€ 컴파일 μ‹œκ°„μ„ μ¦κ°€μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • 디버깅 어렀움: 컴파일 νƒ€μž„μ— μ‹€ν–‰λ˜λŠ” μ½”λ“œμ΄κΈ° λ•Œλ¬Έμ—, 디버깅이 맀우 μ–΄λ ΅μŠ΅λ‹ˆλ‹€.


4. ν™œμš© 사둀

  • κ³ κΈ‰ 라이브러리 개발: ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ€ κ³ κΈ‰ C++ 라이브러리(예: Boost, Eigen, MPL)μ—μ„œ 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
  • 컴파일 νƒ€μž„ 계산: μˆ˜ν•™μ  κ³„μ‚°μ΄λ‚˜ μƒμˆ˜ 생성에 μ‚¬μš©λ©λ‹ˆλ‹€.
  • 정적 λ‹€ν˜•μ„± κ΅¬ν˜„: λŸ°νƒ€μž„ λ‹€ν˜•μ„± λŒ€μ‹  컴파일 νƒ€μž„μ— λ‹€ν˜•μ„±μ„ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 정적 검사: 컴파일 νƒ€μž„μ— νƒ€μž…μ΄λ‚˜ 쑰건을 κ²€μ¦ν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€.

ν…œν”Œλ¦Ώ λ©”νƒ€ν”„λ‘œκ·Έλž˜λ°μ€ C++의 κ°•λ ₯ν•œ κΈ°λŠ₯ 쀑 ν•˜λ‚˜λ‘œ, κ³ κΈ‰ C++ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ ν•„μˆ˜μ μΈ λ„κ΅¬μž…λ‹ˆλ‹€. 이λ₯Ό 톡해 컴파일 νƒ€μž„μ— μ½”λ“œμ˜ μ΅œμ ν™”μ™€ μ•ˆμ „μ„±μ„ 보μž₯ν•  수 있으며, λ³΅μž‘ν•œ 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 데 맀우 μœ μš©ν•©λ‹ˆλ‹€.

μ €μž‘μžν‘œμ‹œ (μƒˆμ°½μ—΄λ¦Ό)

'ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ > C++ μ‘μš©' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Structured Bindings의 λͺ¨λ“  것  (1) 2024.08.27
if-init의 λͺ¨λ“  것(ifλ¬Έ λ‚΄μ—μ„œ λ³€μˆ˜ μ„ μ–Έ, μ΄ˆκΈ°ν™”)  (0) 2024.08.26
[C++] std::optional의 λͺ¨λ“  것  (0) 2024.08.22
[c++] constexpr의 λͺ¨λ“  것  (2) 2024.08.21
클래슀의 크기와 λ©”λͺ¨λ¦¬ ꡬ쑰  (1) 2023.09.14
'ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄/C++ μ‘μš©' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
  • Structured Bindings의 λͺ¨λ“  것
  • if-init의 λͺ¨λ“  것(ifλ¬Έ λ‚΄μ—μ„œ λ³€μˆ˜ μ„ μ–Έ, μ΄ˆκΈ°ν™”)
  • [C++] std::optional의 λͺ¨λ“  것
  • [c++] constexpr의 λͺ¨λ“  것
μ„œμ•„λž‘πŸ˜ƒ
μ„œμ•„λž‘πŸ˜ƒ
Just Do ItπŸ’ͺ
  • μ„œμ•„λž‘πŸ˜ƒ
    G-Stack
    μ„œμ•„λž‘πŸ˜ƒ
  • 전체
    였늘
    μ–΄μ œ
    • 전체보기 (144)
      • ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ (78)
        • C++ 기초 (28)
        • C++ μ‘μš© (18)
        • Python (18)
        • JavaScript & NodeJS (0)
        • Go (12)
        • React & NextJS (2)
        • Java (0)
      • AI (2)
      • 컴퓨터 ꡬ쑰 & 운영체제 (31)
      • μ•Œκ³ λ¦¬μ¦˜ (12)
      • λ°μ΄ν„°λ² μ΄μŠ€ (5)
      • λ„€νŠΈμ›Œν¬ (3)
      • λ””μžμΈνŒ¨ν„΄ (5)
      • μ„œλΉ„μŠ€ & 툴 (7)
      • νŠΈλ Œλ“œ&이슈 (1)
  • λΈ”λ‘œκ·Έ 메뉴

    • ν™ˆ
    • νƒœκ·Έ
    • λ°©λͺ…둝
  • 링크

  • 곡지사항

    • GμŠ€νƒμ˜ 기술 λΈ”λ‘œκ·Έ
  • 인기 κΈ€

  • νƒœκ·Έ

    RAM
    λ°μ΄ν„°λ² μ΄μŠ€
    파이썬
    ν•˜λ“œλ””μŠ€ν¬
    μ•Œκ³ λ¦¬μ¦˜
    pointer
    c++
    반볡문
    컴퓨터
    ν•¨μˆ˜
    상속
    νŒŒμΌμž…μΆœλ ₯
    가상메λͺ¨λ¦¬
    component
    init
    μž¬κ·€
    fork
    STD
    포인터
    νŒ¨ν‚€μ§€
    go
    λ””μžμΈνŒ¨ν„΄
    λ°°μ—΄
    쑰건문
    λ©”λͺ¨λ¦¬
    c
    Thread
    λ³€μˆ˜
    cpu
    μŠ€νƒ
  • 졜근 λŒ“κΈ€

  • 졜근 κΈ€

  • hELLOΒ· Designed Byμ •μƒμš°.v4.10.6
μ„œμ•„λž‘πŸ˜ƒ
ν…œν”Œλ¦Ώ 메타 ν”„λ‘œκ·Έλž˜λ°μ˜ λͺ¨λ“  것(Template Meta Programming)
μƒλ‹¨μœΌλ‘œ

ν‹°μŠ€ν† λ¦¬νˆ΄λ°”