템플릿 -1

·2022년 6월 6일
0

cpp_study

목록 보기
12/25

템플릿이란?

템플릿 명시

template <typename T>

는 아래에 정의되는 클래스에 대해 템플릿을 정의하고, 템플릿 인자로 T 를 받게 되며, T 는 반드시 어떠한 타입의 이름임을 명시함.
이때 아래에 함수가 온다면 이 함수에 대한 템플릿을 정의하는 것임.

클래스 템플릿

초기화

Vector<int> int_vec;

위와 같이 초기화함.
위 코드는 Vector의 T가 int로 치환된 클래스의 객체 int_vec을 생성하는 것.

클래스 템플릿 인스턴스화: 클래스 템플릿에 인자를 전달해서 실제 코드를 생성하는 것

템플릿은 인스턴스화되어야 -> 컴파일러가 실제 코드를 생성함.

BUT bool 데이터를 보관하는 벡터와 같이, 1개 비트로 충분히 처리할 수 있으나 8비트나 이용해야 하는 상황에서(c++은 기본 처리 단위가 1byte임) 특별히 따로 처리해줘야 함.(다음 장 참고)

템플릿 특수화 (template specialization)

템플릿 특수화: 일부 경우에 대해서 따로 처리하는 것

template <typename T> class Vector {
  T* data;
  int capacity; 
  int length;
  // ... 생략 
};

template <>
class Vector<bool> {
  unsigned int* data; 
  int capacity;
  int length;
  // ... 생략 
};
// T가 bool인 경우, 즉 특수한 경우에 대해 처리

이와 같이 bool의 경우 따로 처리할 수 있음.
이때 bool을 1bit로 처리하는 방법에 대해 다룸 - 숙지하고 넘어가는 거 추천

함수 템플릿

#include <iostream>
#include <string>

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

int main() {
  int a = 1, b = 2;
  std::cout << "Max (" << a << "," << b << ") ? : " << max(a, b) << std::endl;
  // Max (1,2) ? : 2
  
  std::string s = "hello", t = "world";
  std::cout << "Max (" << s << "," << t << ") ? : " << max(s, t) << std::endl;
  // Max (hello,world) ? : world
}
  • 템플릿 함수도 코드 상 인스턴스화되기 전까지는 컴파일 시 아무런 코드로 변환되지 않음
  • 클래스를 인스턴스화했을 때와는 다르게 <>하는 부분이 없음
    -> 알아서 인스턴스화해 줌
  • 템플릿으로 발생되는 오류는 프로그램이 실행되었을 때가 아니라 컴파일할 때 발생함
  • 컴파일 시 모든 템플릿들이 인스턴스화된다는 사실 -> 템플릿 메타프로그래밍(template metaprogramming)이라고 함

함수 객체(Function Object- Functor)의 도입

Function Object = 함수 객체(Functor): 함수는 아니지만 함수인 척을 하는 객체

아래 코드에서 comp 객체에 유의해서 살펴 보자.

template <typename Cont, typename Comp>
void bubble_sort(Cont& cont, Comp& comp) { 
  for (int i = 0; i < cont.size(); i++) {
    for (int j = i + 1; j < cont.size(); j++) { 
      if (!comp(cont[i], cont[j])) {
        cont.swap(i, j);
      }
    } 
  }
}

comp는 함수가 아니라 객체 이지만 Comp 클래스에서 () 연산자를 오버로딩해서 마치 함수처럼 사용할 수 있도록 한 함수 객체인 것이다.

struct Comp {
  bool operator()(int a, int b) {
    return a > b;
  }
};

아래 사진 참고.

함수 포인터 vs 함수 객체

여기 링크 참고

-> 이해 잘 안됨

유튜브 링크 1: 함수 포인터
유튜브 링크 2: 함수 객체와 람다

타입이 아닌 템플릿 인자 (non-type template arguments)

#include <iostream>

template <typename T, int num> 
T add_num(T t) {
  return t + num;
}

int main() {
  int x = 3;
  std::cout << "x : " << add_num<int, 5>(x) << std::endl;
  // x : 8
}

위와 같이 template <typename T, int num>을 쓸 수 있음

디폴트 템플릿 인자

#include <iostream>

template <typename T, int num = 5>
T add_num(T t) {
  return t + num;
}

int main() {
  int x = 3;
  std::cout << "x : " << add_num(x) << std::endl;
}

템플릿 디폴트 인자는 함수 디폴트 인자랑 똑같이 인자 뒤에 = (디폴트 값)을 넣어주면 된다.

타입도 디폴트로 지정 가능

#include <iostream>
#include <string>

template <typename T>
struct Compare {
  bool operator()(const T& a, const T& b) const {
    return a < b; 
  } 
};
// 🥰 아래에 집중
template <typename T, typename Comp = Compare<T>>
T Min(T a, T b) {
  Comp comp;
  if (comp(a, b)) {
    return a;
  }    
}
int main() {
  int a = 3, b = 5;
  // 🥰 아래에 집중
  std::cout << "Min " << a << " , " << b << " :: " << Min(a, b) << std::endl;
  std::string s1 = "abc", s2 = "def";
  std::cout << "Min " << s1 << " , " << s2 << " :: " << Min(s1, s2)
             << std::endl;
}

/*
<실행 결과>
Min 3 , 5 :: 3
Min abc , def :: abc
*/
profile
이것저것 개발하는 것 좋아하지만 서버 개발이 제일 좋더라구요..

0개의 댓글