본문 바로가기
C++/[ecourse] C++ Template

1. Template Instantiation

by 헛둘이 2022. 9. 26.

본 글은 코드누리의 Template Programming 강좌를 개인 학습 목적으로 정리한 글 입니다.

https://www.ecourse.co.kr/course-status/

 

템플릿
  • 템플릿은 함수를 만드는 틀
  • 특정 함수에 대해 많은 함수 오버로딩이 필요한 경우 유용하다.

 

 

템플릿 인스턴스화
  • 템플릿은 말 그대로 함수를 만드는 틀이기 때문에 그 자체는 함수가 아니다.
  • 클래스처럼 필요할 때 인스턴스를 만드는 개념
  • 이런 인스턴스는 명시적 인스턴스화, 암시적 인스턴스화로 나뉜다.
  • 암시적 인스턴스화는 통상 평소에 사용하는 것처럼 square<int> a; 이런 식으로 사용하는 것
  • 명시적 인스턴스화는 사용하기 전에 위에서 사용할 것이라고 미리 선언해준다.

 

암시적 인스턴스화
#include <iostream>
#include <boost/type_index.hpp>

using namespace std;
using namespace boost::typeindex;

template<typename T>
T square(T a)
{
	return a * a;
}

int main()
{
	square<int>(3);
	square(3.4);
}

 

  • 함수 템플릿은 사용할 때 템플릿 매개변수 생략이 가능하다.
  • 클래스 템플릿은 C++17부터 생성자를 통해 타입을 추론하므로 템플릿 매개변수 생략이 가능함

 

 

명시적 인스턴스화
template<typename T>
T square(T a) 
{
    return a * a;
}
template int square<int>(int);
template int square(int); // 이렇게 생략해도 사용이 가능
  • template int 함수명<타입>(타입) 이렇게 위에서 미리 선언해두면 알아서 사용함 

 

template<typename T>
class Test
{
public:
    void foo() {}
    void goo() {}
};

template class Test<int>; // foo, goo 모두 인스턴스화
template void Test<int>::foo() // foo만 인스턴스화
  • 클래스 템플릿의 사용 예시
  • 클래스의 경우 사용하지 않은 멤버 함수는 인스턴스화되지 않는다

 


템플릿 타입 디덕션
#include <iostream>

template<typename T>
class Vector
{
	T* buff;
public:
	Vector() {}
	Vector(int sz, T initValue) {}
};

int main()
{
	Vector<int> v1(10, 3); // 10개를 3으로 초기화
	Vector v2(10, 3); // C++17부터 지원
}
  • C++17부터 생성자의 인자를 통해 타입을 결정함
  • 그런데 아래와 같이 타입을 추론할 수 있는 단서를 주지 않으면 에러가 난다.
int main()
{
	Vector v3;
}

 

 

  • 이 경우에는 디덕션 가이드를 만들어줘야 한다.
  • 이런 생성자를 부를 때 인자가 없으면 이 가이드를 따르라~ 식의 해석이 가능할듯
Vector()->Vector<int>;
  • Vector() 생성자가 불릴 때는 특별한 지시가 없다면 Vector<int>로 처리하라는 뜻
  • 이 방식도 C++17부터 지원하며 권장하는 방식은 아님
  • 실질적인 사용 예는 아래와 같다

 

#include <iostream>
#include <list>

template<typename T>
class Vector
{
	T* buff;
public:
	Vector() {}
	Vector(int sz, T initValue) {}


	template<typename C>
	Vector(C& c) {}
};

// 다른 템플릿의 종류로 복사생성될 때 그 템플릿의 타입으로 생성해달라는 것
template<typename C>
Vector(C& c)->Vector<typename C::value_type>;

int main()
{
	std::list l{ 1,2,3 };
	Vector v3(l);
}
  • 벡터의 타입을 리스트의 타입으로 맞추고 싶은데 typename C로 들어오는 인자는 list<int>이므로
  • list의 타입인 int를 추출해내기 위한 방법의 일환 

 

 

 


템플릿을 사용할 때 주의할 점
  • 템플릿은 다른 기존 함수처럼 함수의 선언만 헤더에 두면 안됨
  • 컴파일러가 함수 인스턴스를 만들 때 헤더 파일을 참조하기 때문
  • 그래서 헤더 쪽에 구현까지 다 포함시켜야 함
  • 마찬가지의 이유로 클래스 템플릿의 멤버 함수도 마찬가지로 바깥으로 뽑으면 안됨

 

 

 

 

 


지연된 인스턴스화
  • 클래스 템플릿의 멤버 함수에서 int형을 역참조하는 경우 원래 에러가 나야 하는데 에러가 나지 않음
  • 사용하지 않아서 인스턴스화 되지 않았기 때문
  • 실제 사용되지 않으면 C++ 코드로 만들어지지 않는다.
  • 이걸 지연된 인스턴스화라고 한다.
  • 실제로 사용하면 그 때 에러가 발생함
- 클래스 템플릿의 static 멤버 변수는 외부선언할 때 template<typename T>를 붙여줘야 함
- 클래스템플릿의 static 멤버 변수는 실제 사용되지 않으면 인스턴스화되지 않음
#include <iostream>

class Resource1
{
public:
	Resource1() { std::cout << "Resource1()" << std::endl; }
	~Resource1() { std::cout << "~Resource1()" << std::endl; }
};

class Resource2
{
public:
	Resource2(){std::cout << "Resource2()" << std::endl;}
	~Resource2(){std::cout << "~Resource2()" << std::endl;}
};

template<typename T> struct Test
{
	Resource1 res1;
	static Resource2 res2;
};
template<typename T> Resource2 Test<T>::res2;


int main()
{
	std::cout << "Main" << std::endl;

	Test<int> t;
}

Main
Resource1()
~Resource1()

 

  • 위에서 언급했듯 실제 사용되지 않아서 초기화되지 않았음

 

int main()
{
	std::cout << "Main" << std::endl;

	Test<int> t;
	t.res2;
}
  • 메인에 이렇게 사용하는 코드를 추가하면 그제서야 만들어짐

 

Resource2()
Main
Resource1()
~Resource1()
~Resource2()

 

 

 

 

 

 


if문과 지연된 인스턴스화
#include <iostream>

template<typename T> void foo(T n)
{
	*n = 10;
}

int main()
{
	if (false)
		foo(0);
}
  • if문은 실행시간 조건문이라 템플릿 함수 안에 if(false)로 놓고 if문 안에 에러가 발생하는 코드를 집어넣어도
  • 런타임에 사용될 수 있다고 여겨서 인스턴스화되고, 결과적으로 에러가 발생한다.

 

 

if constexpr (C++17)
#include <iostream>

template<typename T> void foo(T n)
{
	*n = 10;
}

int main()
{
	if constexpr (false)
		foo(0);
}
  • constexpr은 이 if문이 실행될것인지를 컴파일시간에 판별한다.
  • 그래서 위 문법은 에러가 나지 않는다.

'C++ > [ecourse] C++ Template' 카테고리의 다른 글

6. 템플릿 특수화  (1) 2022.09.29
5. 템플릿 기본 문법 - typename, template  (0) 2022.09.28
4. 템플릿 기본 문법 - 클래스 템플릿  (0) 2022.09.27
3. 배열과 템플릿  (0) 2022.09.26
2. Template Type Deduction  (0) 2022.09.26

댓글