본문 바로가기

Programming/CPP11&14

[C++11] std::pair를 확장한 std::tuple

반응형

Boost에 존재하던 tuple이 C++ 표준으로 채택되었습니다.

C++ TR1부터 사용이 가능해졌지만 C++11에 분류한 것은 이전에 작성한 가변인자 템플릿때문입니다.

tuple은 기존의 std::pair를 확장한 자료형입니다.

std::pair가 2개의 값을 한 번에 저장할 수 있지만 tuple은 제한이 없습니다.

기존의 C++ TR1에서는 10개까지 저장이 되었습니다.

tuple은 2개 이상의 값을 한 번에 반환하거나 전달할 때 사용하면 유용합니다.

물론 구조체를 통해서 가능한 방법이긴 하지만 구조체는 정의를 해서 사용해야 합니다.

tuple을 이용하면 간단하게 다양한 값들을 한 번에 전달이 가능하게 됩니다.

예제 코드는 다음과 같습니다.

#include <tuple>
#include <string>
#include <iostream>

int main()
{
	// make tuple variable.
	typedef std::tuple<int, std::string, bool> OddOrEven;
	OddOrEven myNumber = std::make_tuple(10, std::string("Even"), true);

	// get tuple size
	std::cout << "size : " << std::tuple_size<decltype(myNumber)>::value << std::endl;

	// get each value and get type using std::tuple_element, auto keyword.
	std::tuple_element<0, decltype(myNumber)>::type nNum = std::get<0>(myNumber);
	auto szVal = std::get<1>(myNumber);
	bool bEven = std::get<2>(myNumber);

	std::cout << nNum << ", " << szVal << ", " << std::boolalpha << bEven << std::endl;

	return 0;
}

먼저, std::tuple<> 안의 <> 안에 필요한 변수 타입들을 작성합니다.

typedef로 해당 타입을 OddOrEven 타입이라고 명명했습니다.

tuple 변수에 값을 넣을 때는 std::make_tuple()을 사용하면 됩니다.

해당하는 위치에 해당하는 값을 넣으면 생성이 됩니다.

tuple 안에 몇 개의 변수가 존재하는지는 std::tuple_size<decltype(myNumber)>::value로 가능합니다.

decltype(myNumber)는 C++11에서 생긴 문법으로 해당 변수의 타입을 유추해줍니다.

간단하게 auto와 비슷한 기능이라고 할 수 있습니다.

값을 가져올 때는 std::get<n>(myNumber)로 가져올 수 있습니다.

인덱스는 0부터 시작해서 해당하는 위치의 값을 가져옵니다.

std::tuple_element를 사용해서 tuple의 특정 위치의 타입을 가져올 수 있습니다.

또한 auto 키워드, 혹은 직접 타입을 명시하는 것도 가능합니다.

결과는 다음과 같이 출력됩니다.

값들이 정상적으로 출력되는 것을 확인할 수 있습니다.

그 외에 tuple에서 사용되는 함수들입니다.

#include <tuple>
#include <string>
#include <iostream>

void print(std::tuple<int, bool> tVal)
{
	std::cout << std::get<0>(tVal) << ", " << std::get<1>(tVal) << std::endl;
}

int main()
{
	// make tuple variable.
	typedef std::tuple<int, std::string, bool> OddOrEven;
	OddOrEven myNumber1 = std::make_tuple(10, std::string("Even"), true);
	OddOrEven myNumber2 = std::make_tuple(7, std::string("Odd"), false);

	// std::tie() and std::ignore.
	int nVal;
	bool bEven;

	std::tie(nVal, std::ignore, bEven) = myNumber1;
	std::cout << nVal << ", " << bEven << std::endl;

	// tuple_cat function.
	auto myNums = std::tuple_cat(myNumber1, myNumber2);

	std::cout << "Value 1 : " << std::get<0>(myNums) << ", " << std::get<1>(myNums) << ", " << std::get<2>(myNums) << std::endl;
	std::cout << "Value 2 : " << std::get<3>(myNums) << ", " << std::get<4>(myNums) << ", " << std::get<5>(myNums) << std::endl;

	// foward_as_tuple
	print(std::forward_as_tuple(nVal, bEven));

	return 0;
}

std::tie는 개별 변수들을 tuple처럼 만들어서 tuple의 각 위치의 값을 가져옵니다.

std::ignore를 사용하면 해당 위치는 값을 가져오지 않게 됩니다.

그 외에 std::tuple_cat은 서로 다른 두 타입의 tuple을 한 개로 연결해서 생성하는 역할을 합니다.

그리고 tuple 타입을 받는 함수에 변수를 생성하지 않고 전달할 수 있는 std::forward_as_tuple도 존재합니다.

tuple은 구조체를 정의하지 않고도 값의 조합을 생성할 수 있기 때문에 유용하게 활용이 가능합니다.

반응형