← SEARCHABLE ARCHIVE
C / C++ · 2026-07-22

C++ 기초부터 마스터까지 — 13화

템플릿으로 타입이 다른 중복 코드 줄이기

INTERACTIVE READING MODE →

본 블로그 작성 글들은, 강의를 목표로 하고 제작되었습니다. 또한 작성된 글의 정보도 틀렸을 수 있으니, 주의해주세요.

아이템 ID를 찾는 함수와 몬스터 ID를 찾는 함수가 거의 같은 모양일 때가 있다. 자료형만 다르고 동작이 같다면 코드를 복사하기보다 템플릿으로 공통 규칙을 만들 수 있다.

함수 템플릿

두 값 중 큰 값을 반환하는 함수부터 만들어보자.

template <typename T>
T Max(const T& a, const T& b)
{
    return a < b ? b : a;
}

int highLevel = Max(10, 20);
float highDamage = Max(12.5f, 8.0f);

T는 함수를 호출할 때 실제 타입으로 바뀌는 자리이다. 컴파일러는 Max<int>와 Max<float>처럼 필요한 함수를 각각 만들어낸다.

다만 Max(10, 3.5f)처럼 서로 다른 타입을 전달하면 하나의 T를 결정할 수 없어 컴파일에 실패한다. 명시적으로 타입을 맞추거나 두 타입을 받는 템플릿을 따로 설계해야 한다.

클래스 템플릿

같은 크기의 슬롯을 여러 타입에 사용하고 싶다면 클래스도 템플릿으로 만들 수 있다.

template <typename T, std::size_t Size>
class Inventory
{
public:
    T& At(std::size_t index)
    {
        return slots.at(index);
    }

    const T& At(std::size_t index) const
    {
        return slots.at(index);
    }

private:
    std::array<T, Size> slots{};
};

Inventory<Item, 20> itemInventory;
Inventory<Skill, 8> skillInventory;

T는 타입이고 Size는 컴파일할 때 정해지는 값이다. std::array의 크기는 런타임에 바뀌지 않으므로 고정 슬롯을 표현하기 좋다.

템플릿과 헤더 파일

일반 함수는 선언을 헤더에 두고 정의를 cpp에 둘 수 있다. 하지만 템플릿은 컴파일러가 실제 타입에 맞는 코드를 만드는 시점에 정의를 볼 수 있어야 한다.

// Inventory.h
template <typename T>
class Inventory
{
public:
    void Add(const T& value)
    {
        values.push_back(value);
    }

private:
    std::vector<T> values;
};

그래서 템플릿 정의는 보통 헤더에 작성한다. 선언만 헤더에 두고 정의를 cpp로 숨기면 특정 타입의 코드를 찾지 못해 링크 오류가 날 수 있다.

템플릿을 사용할 기준

타입만 다르고 의미가 같은 코드라면 템플릿이 중복을 줄여준다. 반대로 동작과 책임까지 다른 코드를 억지로 하나의 템플릿에 넣으면 조건문과 특수 처리가 늘어난다.

템플릿은 모든 코드를 일반화하는 기능이 아니다. 같은 규칙을 여러 타입에 안전하게 적용하고, 잘못된 조합은 컴파일 단계에서 막는 도구라고 생각하는 편이 좋다.