프로그래밍/C++

템플릿(Template) 프로그래밍 2

hscho00 2020. 8. 10. 15:38

FixedVector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#pragma once
 
template<typename T, size_t N>
class FixedVector
{
public:
    FixedVector();
 
    bool Add(const T& data);
    size_t GetSize() const;
    size_t GetCapacity() const;
 
private:
    size_t mSize;
    T mArray[N];
 
};
 
template<typename T, size_t N>
FixedVector<T, N>::FixedVector()
    : mSize(0), mArray()
{
 
}
 
template<typename T, size_t N>
size_t FixedVector<T, N>::GetSize() const
{
    return mSize;
}
 
template<typename T, size_t N>
size_t FixedVector<T, N>::GetCapacity() const
{
    return N;
}
 
template<typename T, size_t N>
bool FixedVector<T, N>::Add(const T& data)
{
    if (mSize >= N)
    {
        return false;
    }
 
    mArray[mSize++= data;
 
    return true;
}
cs

MyPair

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma once
 
template<typename T, typename U>
class MyFair
{
public:
    const T& GetFirst() const;
    const U& GetSecond() const;
    MyFair(const T& first, const U& second);
 
private:
    T mFirst;
    U mSecond;
 
};
 
template<typename T, typename U>
const T& MyFair<T, U>::GetFirst() const
{
    return mFirst;
}
 
template<typename T, typename U>
const U& MyFair<T, U>::GetSecond() const
{
    return mSecond;
}
 
template<typename T, typename U>
MyFair<T, U>::MyFair(const T& frist, const U& second)
    : mFirst(first), mSecond(second)
{
 
}
cs

Math

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma once
 
namespace Math
{
    template<typename T>
    static T Add(T value1, T value2)
    {
        return value1 + value2;
    }
 
    template<typename T>
    static T Divide(T value1, T value2)
    {
        return value1 / value2;
    }
 
    template<typename T>
    static T Multiply(T value1, T value2)
    {
        return value1 * value2;
    }
 
    template<typename T>
    static T Max(T value1, T value2)
    {
        return value1 < value2 ? value2 : value1;
    }
 
    template<typename T>
    static T Min(T value1, T value2)
    {
        return value1 < value2 ? value1 : value2;
    }
}
cs

템플릿 특수화(Specialization)

특정한 템플릿 매개변수를 받도록 템플릿 코드를 커스터마이즈 할 수 있음

 

제네릭 템플릿이 어느 형에나 적용됨

단, 특정 형에 특수화된 템플릿이 있다면 그 특수화된 템플릿이 적용됨

그렇게 자주 쓰이지는 않음

 

 

> std::vector에 좋은 예

template <class T, class Allocator>

class std::vector<T, Allocator> {} // 모든 형을 받는 제네릭 vector

 

template <class Allocator>

class std::vector<bool, Allocator> {} // bool을 받도록 특수화된 vector

 

bool은 왜 다를까?

> 하나의 비트로도 표현할 수 있지만, bool은 1바이트, BOOL은 4바이트를 사용

> 메모리 공간을 조금 더 효과적으로 사용하기 위해 템플릿 특수화를 했다고 볼 수 있음


전체 템플릿 특수화

> 템플릿 매개변수 리스트가 비어 있음

template<typename VAL, typename EXP>

VAL Power(const VAL value, EXP exponent) () // 모든 형을 받는 제네릭 Power()

 

template<>

float Power(float value, float exp) {}              // float을 받도록 특수화된 Power()

 

 

부분 템플릿 특수화

template<class T, class Allocator>

class std::vector(T, Allocator> {}    // 모든 형을 받는 제네릭 vector

 

template<class Allocator>

class std::vector(bool, Allocator) {} // bool을 받도록 특수화된 vector


템플릿 프로그래밍의 장점과 단점

 

컴파일러가 컴파일 도중에 각 템플릿 인스턴스에 대한 코드를 만들어 줌

> 컴파일 타임은 비교적 느림

> 템플릿 매개변수를 추가할수록 더 느려짐

 

> 하지만 런타임 속도는 더 빠를지도 모름

> 실행 파일 크기가 커지기 때문에 항상 그런 것은 아님 (캐시 효용성이 떨어져서)

> C#과 Java도 어느 정도 해당되는 말 (그래서 ArrayList를 쓰지 말라는 것)

 

자료형만 다른 중복 코드를 없애는 훌륭한 방법

하지만 쓸모없는 템플릿 변형을 막을 방법이 없음

> Add<int>, Add<short>, Add<unsigned int>

> Vector<3>, Vector<4>, Vector<15> (템플릿 매개변수는 요소의 수)

 

> 최대한 제네릭 함수를 짧게 유지할 것 (코드의 크기가 커지므로)

> 제네릭이 아니어도 되는 부분은 별도의 함수로 옮기는 것도 방법. 이 함수가 인라인 될 수도 있음.

 

컴파일 도중에 다형성을 부여할 수 있음

> C++ 프로그래머가 너무 많이 잘못 썼던 기능

> 가상 테이블이 없어서 프로그램이 더 빠름

> 하지만 exe 파일이 커지면 느려질 수 있음

 

코드 읽기가 더 힘듦

 

디버깅이 좀 이상할 수 있음

> 더 이상 큰 문제는 아니지만...


템플릿 프로그래밍 베스트 프랙티스

 

컨테이너의 경우 매우 적합

> 아주 다양한 형들을 저장할 수 있음

> 그런 이유로 Java와 C# 제네릭이 주로 컨테이너에 쓰이는 것

 

컨테이너가 아닌 경우

> 각기 다른 서넛 이상의 자료형을 다룬다면 템플릿을 쓰자

> 두 가지 정도라면 그냥 클래스를 2개 만들자

    class Math;

    class FloatMath;

 

 

 

출처 : 포큐아카데미 C++ 언매니지드 프로그래밍