본문 바로가기
💻 programming/c++

[c++] variadic template (가변 길이 템플릿)

by 연구원-A 2020. 12. 15.
반응형

Variadic Template

Variadic function templates in C++ - GeeksforGeeks

가변 길이 템플릿 (Variadic template)은 여러개의 인자를 가질 수 있습니다.

예를 들어 가변 길이 템플릿을 이용하여 정의한 함수 템플릿정해진 숫자가 아닌 가변 길이 인자를 받을 수 있습니다.

Syntax for a variadic function template

아래 코드에서 typename 뒤에 선언된 "..."이 템플릿 파라미터 팩 (parameter pack)입니다.

이 템플릿 파라미터 팩을 선언하면 이 템플릿은 0개 이상의 (가변된 길이의) 인자를 받을 수 있다는 뜻입니다.

template (typename arg, typename... args)
return_type function)name(arg var1, args... var2)

Sample code

아래 소스 코드는 가변 길이 템플릿을 이용하여 여러 개의 인자를 전달받아 화면에 출력하는 예시입니다.

 

화면에 출력하기 위해 void print( ) 함수를 정의하였는데, 가변 길이 템플릿에서 print ( ) 함수를 호출하기 때문에 void print( ) 함수를 variadic template 아래에 구현하면 컴파일 에러가 발생합니다. 컴파일러는 해당 소스 코드의 앞에 정의 되어 있는 함수밖에 읽지 못하기 때문입니다.

 

또, c++11에 도입된 가변 길이 템플릿은 한 가지 단점이 있습니다. 재귀 함수 형태로 구성해야 하기 때문에 반드시 재귀 종료 함수 (base case)를 따로 만들어야 한다는 점입니다.

 

하지만 c++17에 도입된 fold 형식을 사용한다면 훨씬 간단하게 표현할 수 있습니다. 📢 Fold Expression

// C++ program to demonstrate working of Variadic function template
#include <iostream>
using namespace std;

// To handle base case of below recursive
// Variadic function Template
void print() {
    cout << "I am empty function and I am called at last. " << endl;
}

// Variadic function template that thakes variable number of argumnets and prints all of them
template <typename T, typename... Types>
void print(T var1, Tpes... var2) {
    cout << var << endl;
    print(var2...);
}

// Driver code
int main() {
    Pirnt(1, 2, 3.14, "Pass me any number of arguments", "I will print");
}

Explanation

아래 구문은 다음의 순서로 해석됩니다.

print(1, 2, 3.1, "Pass me any number of argymnets", "I will print");

첫 번째로 컴파일러는 구문을 다음과 같이 변환합니다. var1에는 1이 전달되고, var2 에는 2, 3.14, ... 이 전달되기 때문입니다.

cout << 1 << endl;
print(2, 3.14, "Pass me any number of arguments", "I will print");

위 과정을 반복하면 인자가 없는 empty 함수를 호출하게 됩니다.

// cout << 1 << endl;
// cout << 2 << endl;
// cout << 3.14 << endl;
// cout << "Pass me any number of arguments" << endl;
// cout << I will print" << endl;
print();

sizeof...

sizeof 연산자는 인자의 크기를 반환하지만, 파라미터 팩으로 전달받은 인자에 sizeof... 연산자를 사용하면 전체 인자의 개수를 반환합니다.

#include <iostream>

// 재귀 호출 종료를 위한 베이스 케이스
int sum_all() { return 0; }

template <typename... Ints>
int sum_all(int num, Ints... nums) {
  return num + sum_all(nums...);
}

template <typename... Ints>
double average(Ints... nums) {
  return static_cast<double>(sum_all(nums...)) / sizeof...(nums);
}

int main() {
  // (1 + 4 + 2 + 3 + 10) / 5
  std::cout << average(1, 4, 2, 3, 10) << std::endl;
}
반응형

'💻 programming > c++' 카테고리의 다른 글

[c++] mutex, lock guard, unique lock, shared mutex, recursive mutex  (0) 2020.12.16
[c++] template meta programming  (0) 2020.12.15
[c++] functor (function object)  (0) 2020.12.15
[c++] template specialization  (0) 2020.12.15
[c++] template  (0) 2020.12.15

댓글