갯수가 정해지지 않은 N개의 인자를 사용 할 수 있는 기능으로써 D언어와 C++ 11에서 지원하고 있다

(from. http://en.wikipedia.org/wiki/Variadic_template)


C++ 11 이전 버젼의 템플릿에서는 지정된 갯수만큼의 인자만을 받을 수 있었으나 C++11에서 부터는 임의의 갯수를 받을 수 있도록 변경 되었다. 기본적인 문법은 아래와 같다 :


template<typename... Values> class tuple;


위의 템플릿 클래스 tuple은 어떠한 타입이든 몇개든 상관 없이 템플릿 인자 생성이 가능 하다. 예를 들어서 위 클래스의 인스턴스로 아래와 같은 것이 가능하다 :


tuple<int, std::vector<int>, std::map<std::string, std::vector<int>>> some_instance_name;


물론 0개의 템플릿 인자로도 인스턴스 생성이 가능하고 tuple<>some_instance_name 과 같은 코드도 정상 동작한다. 만일 최소한 하나의 인자는 받아야 한다라고 강제하고 싶다면 아래와 같은 코드도 가능 하다 :


template<typename First, typename... Rest> class tuple;


위 코드에서는 tuple<> some_instance_name 과 같은 코드는 컴파일 에러를 발생 시킨다.


Variadic template은 템플릿 특화(Template specialize)와 결합해서 사용하면 가변인자를 이용한 함수(va_list) 와 같은 기능을 하지만 %c, %d와 같은 귀찮은 예약 인자와 순서를 맞춰야만 하는 귀찮음을 제거 할 수 있는 강력한 도구가 된다. 아래 코드는 임의의  타입으로 구성된 임의의 갯수의 인자를 받아 결합하여 문자열로 리턴 하는 함수를 variadic template을 이용하여 구현 한것이다 :

#include <string>

#include <sstream>

#include <iostream>

template <class T>

void Concat(std::stringstream& stream, const T& t) // 종료 템플릿 함수

{

        stream << t;

}


template <class T, class... ARGS>

void Concat(std::stringstream& stream, const T& t, ARGS&&... args) // 재귀 템플릿 함수

{

        stream << t;

        Concat(stream, args...);

}


template <class... ARGS>

std::string Concat(ARGS... args) // 유저 호출 함수

{

        std::stringstream stream;

        Concat(stream, args...); // 템플릿 특화로 인해 재귀 템플릿 함수가 호출 된다.

        return stream.str();

}


int main()

{

        int n100 = 100;

        int n200 = 200;

        float f100 = 100.0f;

        float f200 = 200.0f;

        std::string str = "string out";

        std::cout << Concat("string ", n100, " ", str, " ", n200, " ", f100, " ", f200 ) << std::endl;

           printf("string %d %s %d %f %f", n100, str.c_str(), n200, f100, f200);

        return 0;

}


ref :

 - http://en.wikipedia.org/wiki/Variadic_template

Posted by kukuta

댓글을 달아 주세요