C++

[C++] 클래스 템플릿(class template)

코딩 메모장 2024. 11. 21. 21:22
728x90

C++에서 **클래스 템플릿(class template)**은 여러 데이터 타입에 대해 동일한 클래스를 정의할 수 있게 해주는 기능입니다. 이를 통해 코드의 재사용성유연성을 높일 수 있으며, 다양한 데이터 타입에 대해 동일한 로직을 적용할 수 있습니다.

 

기본 개념

클래스 템플릿은 template 키워드를 사용하여 정의되며, **타입 매개변수(type parameter)**를 사용해 클래스의 멤버 변수와 메서드의 타입을 동적으로 결정합니다.

 

기본 문법

template <typename T>
class ClassName {
public:
    T memberVariable; // 템플릿 타입을 사용하는 멤버 변수

    ClassName(T value) : memberVariable(value) {} // 생성자

    T getValue() const { // 템플릿 타입을 사용하는 멤버 함수
        return memberVariable;
    }
};

 

예제

1. 기본 클래스 템플릿

#include <iostream>

template <typename T>
class Box {
public:
    T value;

    Box(T v) : value(v) {}

    T getValue() const {
        return value;
    }
};

int main() {
    Box<int> intBox(123);
    Box<double> doubleBox(45.67);

    std::cout << "intBox value: " << intBox.getValue() << std::endl;       // 123
    std::cout << "doubleBox value: " << doubleBox.getValue() << std::endl; // 45.67

    return 0;
}

2. 다중 타입 매개변수

클래스 템플릿은 여러 타입 매개변수를 지원합니다.

#include <iostream>

template <typename T, typename U>
class Pair {
public:
    T first;
    U second;

    Pair(T f, U s) : first(f), second(s) {}

    void display() const {
        std::cout << "First: " << first << ", Second: " << second << std::endl;
    }
};

int main() {
    Pair<int, double> p(1, 2.5);
    p.display(); // First: 1, Second: 2.5

    return 0;
}

3. 템플릿 기본값

템플릿 매개변수에 기본값을 설정할 수 있습니다.

#include <iostream>

template <typename T = int>
class Container {
public:
    T value;

    Container(T v) : value(v) {}

    T getValue() const {
        return value;
    }
};

int main() {
    Container<> defaultContainer(10); // 기본값(int) 사용
    Container<double> doubleContainer(3.14);

    std::cout << "Default Container: " << defaultContainer.getValue() << std::endl; // 10
    std::cout << "Double Container: " << doubleContainer.getValue() << std::endl;   // 3.14

    return 0;
}

추가 주제

1. 템플릿 특수화

특정 타입에 대해 동작을 변경하려면 명시적 특수화를 사용할 수 있습니다.

#include <iostream>

template <typename T>
class Printer {
public:
    void print(T value) {
        std::cout << "Value: " << value << std::endl;
    }
};

// 특수화
template <>
class Printer<char> {
public:
    void print(char value) {
        std::cout << "Character: " << value << std::endl;
    }
};

int main() {
    Printer<int> intPrinter;
    Printer<char> charPrinter;

    intPrinter.print(42);      // Value: 42
    charPrinter.print('A');    // Character: A

    return 0;
}

2. 부분 특수화

부분 특수화는 템플릿의 일부 조건에서 동작을 변경하는 데 유용합니다.

#include <iostream>

template <typename T, typename U>
class Pair {
public:
    void display() {
        std::cout << "Generic Pair" << std::endl;
    }
};

// 부분 특수화: 두 타입이 동일한 경우
template <typename T>
class Pair<T, T> {
public:
    void display() {
        std::cout << "Homogeneous Pair" << std::endl;
    }
};

int main() {
    Pair<int, double> genericPair;
    Pair<int, int> homogeneousPair;

    genericPair.display();       // Generic Pair
    homogeneousPair.display();   // Homogeneous Pair

    return 0;
}

3. 클래스 템플릿과 상속

템플릿 클래스는 상속 관계에서도 활용 가능합니다.

#include <iostream>

template <typename T>
class Base {
public:
    void display() {
        std::cout << "Base class" << std::endl;
    }
};

template <typename T>
class Derived : public Base<T> {
public:
    void display() {
        std::cout << "Derived class" << std::endl;
    }
};

int main() {
    Derived<int> derived;
    derived.display(); // Derived class

    return 0;
}

4. 템플릿 매개변수 제약 (C++20)

C++20에서는 **컨셉(Concept)**을 사용해 타입 매개변수에 제약 조건을 추가할 수 있습니다.

#include <concepts>
#include <iostream>

template <typename T>
requires std::integral<T> // T는 정수 타입이어야 함
class IntegerBox {
public:
    T value;
    IntegerBox(T v) : value(v) {}
};

int main() {
    IntegerBox<int> validBox(42);    // OK
    // IntegerBox<double> invalidBox(3.14); // 컴파일 에러

    std::cout << "ValidBox value: " << validBox.value << std::endl;
    return 0;
}

장점

  1. 코드 재사용성: 여러 데이터 타입에 대해 동일한 클래스 로직을 사용할 수 있습니다.
  2. 유연성: 다양한 타입을 다룰 수 있어 코드 작성이 더욱 효율적입니다.
  3. 타입 안전성: 컴파일 타임에 타입 검사가 이루어져, 런타임 오류를 줄일 수 있습니다.

결론

클래스 템플릿은 C++에서 강력하고 유연한 기능으로, 다양한 데이터 타입을 효율적으로 처리할 수 있습니다. 특히 템플릿 특수화, 상속, C++20의 컨셉과 결합하면 더욱 강력한 도구로 활용할 수 있습니다. 코드를 재사용하면서도 안전성과 확장성을 모두 충족시킬 수 있는 필수 기능입니다.

728x90