[C++] 2개 이상의 묶음으로 저장(std::tuple)
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함수를 쓰면 자동으로
우선적으로 나이를 기준으로,(오름차순)
나이가 같다면 가입번수를 기준으로,(오름차순)
나이와 가입번수도 같다면 이름을 기준으로(사전순) 정렬
해주기 때문에 매우 유용함.
댓글남기기