std::pair의 확장판 느낌인 std::tuple

헤더파일

#include<tuple>


선언

tuple<int,int,double,string> t;

2개,3개,4개,5개… 등 원하는 만큼의 자료형을 묶을 수 있음.


값 생성(변경)

tuple<int,int,double,string> t = make_tuple(1,2,3.3,"hello");

make_tuple( )을 사용함.


값 얻기

cout<<get<0>(t);

get<원하는 요소의 인덱스>(튜플 변수)

튜플변수의 이름을t라고 했을때

위와 같이 코드를 쓰면 t변수의 첫번째 값을 리턴해줌.


튜플 속 원소 개수 얻기

std::tuple_size<decltype(t)>::value
    
또는
    
std::tuple_size_v<decltype(t)>

std::tuple_size<decltype(튜플변수)>::value

std::tuple_size_v<decltype(튜플변수)>

위 코드를 통해 몇개의 변수로 이루어져있는지 알 수 있음.

ex)

tuple<int,int,double,string> t;
cout<<std::tuple_size<decltype(t)>::value; // 4 출력됨


특정 위치의 타입 얻기

tuple<int,int,double,string> t;

std::tuple_element<0,decltype(t)>::type temp=3;
또는
std::tuple_element_t<0,decltype(t)> temp=3;

std::tuple_size<decltype(튜플변수)>::type

std::tuple_size_t<decltype(튜플변수)>

위 코드의 경우 튜플변수 t의 0번째 타입이 int이기 때문에

temp변수의 타입은 int가 됨.


std::tie와 std::ignore 사용

tuple<int,int,double,string> t;

t=make_tuple(1, 2, 3.3, "hello");

int a;
double b;
string str;

std::tie(a, std::ignore, b, str) = t;
//a에 1 저장됨
//b에 3.3 저장됨
//str에 hello 저장됨

튜플에 있는 값을 한번에 깔끔하게 다른 변수에 저장하고 싶을때 std::tie를 사용.

이떄, 중간에 저장하고 싶지 않은 변수가 있다면,

해당 변수의 순서에 std::ignore를 써주면

해당 변수를 건너뒴.


std::tuple_cat

여러개의 tuple을 묶어서 새로운 tuple을 생성할 때 사용함.

tuple<int,string,double> t1=make_tuple(1,"hello",2.2);
tuple<char,string> t2=make_tuple('c',"world!");
tuple<double,double,double> t3=make_tuple(3.3,4.4,5.5);

auto a=std::tuple_cat(t1,t2,t3);
cout<<get<4>(a);
//world! 출력됨

std::tuple_cat(튜플변수1, 튜플변수2, 튜플변수3, …)


std::forward_as_tuple

tuple타입을 받는 함수에 변수를 생성하지 않고 전달하기 위해 사용함.

using namespace std;

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

int main()
{
    print(forward_as_tuple(1,string("hello")));
    
    print(make_tuple(2,string("world"))); // 이것도 가능하긴 함
}

forward_as_tuple로 인자를 넘겨준다면 rvalue references(우측값 참조)로 넘겨준다는 특징이 있음.

(make_tuple로 바로 인자로 넘겨줘도 같은 효과가 있는 것 같습니다?? 아마..)


이때 주의할점은

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

int main()
{
   string str="Test";
    
    print(forward_as_tuple(1,str+"hello")); //이건 Testhello가 우측값 참조가 됨 O
    print(forward_as_tuple(2,"hello")); //hello가 우측값 참조가 안됨 X  
    
    
    //출력결과:
    1, Testhello
    2,
}

위 코드처럼

string을 인자로 줄때,

“hello”처럼 단순 char배열을 넘겨줄 경우, rvalue참조 string타입으로 자동변환이 안되기 때문에 정상적인 작동을 하지 않음.


그러나 string변수+char배열(“~~~~”)

형식으로 넘겨줄 경우,

먼저 string 변수로 생성이 된 다음에

그 값이 rvalue string이기때문에 정상적으로 작동함.


유용한 사용법

알고리즘 문제를 풀 때, sort함수와 같이 사용하면 유용함.

    int n;
    cin>>n;
    vector<tuple<int,int,string>> v; //나이, 가입번수, 이름

    for(int i=0; i<n; i++)
    {
        int age;
        string name;
        cin>>age>>name;

        tuple<int,int,string> t=make_tuple(age,i,name);
        v.push_back(t);
    }

    sort(v.begin(),v.end());

    for(int i=0; i<n; i++)
    {
        cout<<get<0>(v[i])<<" "<<get<2>(v[i])<<"\n";
    }

이런식으로, vector에 tuple변수를 담을 경우,

sort(v.begin(),v.end());

를 하면 tuple변수에 담긴 순서를 기준으로 정렬을 해줌.


예를 들어 위 코드같이

tuple을 저장할때

첫 번째나이,

두 번째가입번수,알고리즘 문제를 풀 때, sort함수와 같이 사용하면 유용함.

    int n;
    cin>>n;
    vector<tuple<int,int,string>> v; //나이, 가입번수, 이름

    for(int i=0; i<n; i++)
    {
        int age;
        string name;
        cin>>age>>name;

        tuple<int,int,string> t=make_tuple(age,i,name);
        v.push_back(t);
    }

    sort(v.begin(),v.end());

    for(int i=0; i<n; i++)
    {
        cout<<get<0>(v[i])<<" "<<get<2>(v[i])<<"\n";
    }

이런식으로, vector에 tuple변수를 담을 경우,

sort(v.begin(),v.end());

를 하면 tuple변수에 담긴 순서를 기준으로 정렬을 해줌.


예를 들어 위 코드같이

tuple을 저장할때

첫 번째나이,

두 번째가입번수,

세 번째이름


을 저장했기 때문에, sort함수를 쓰면 자동으로

우선적으로 나이를 기준으로,(오름차순)

나이가 같다면 가입번수를 기준으로,(오름차순)

나이와 가입번수도 같다면 이름을 기준으로(사전순) 정렬

해주기 때문에 매우 유용함.

카테고리:

업데이트:

댓글남기기