• <tuple>이 있다는 것을 알게 되었다.

  • pair<int, pair<string, int>>와 같은 선언과 s.first.second.second와 같은 귀찮고 보기 힘든 내용을 싹 정리해준다.

  • 소스코드만 봐도 tuple에 관해 직관적으로 이해할 수 있기 때문에 코드를 먼저 보는게 나을 것 같다.

소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<tuple>
#include<string>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;

typedef tuple<int, int, int, string> stds;

int main()
{
	int n;
	cin>>n;
	vector<stds> s(n);
	for(int i=0;i<n;i++){
		string st;
		int a, b, c;
		cin>>st>>a>>b>>c;
		s[i]=make_tuple(-a, b, -c, st);
	}
	sort(s.begin(), s.end());
	for(auto it:s) cout<<get<3>(it)<<'\n';
}

<tuple>의 함수들

  • tuple<VTypes...> make_tuple (Types&&... args)
    • make_pair과 같은 역할의 함수다. 선언한 tuple의 type에 맞춰 호출하면 된다.
Types 뒤의 &&는 뭔가요??

명칭은 우측값 참조(Rvalue reference)라고 한다.
먼저 좌측/우측값에 대해 짚고 넘어가자면, C++기준으로 &을 통해 레퍼런스를 만들 수 있으면 LvalueRvalue는 그게 아닌 값들이다.
대입연산자 =를 정의할 때 =뒤에 오는 값이 LvalueRvalue냐에 따라서 처리하는 방법이 달라진다. a=b에 대해 b가 Lvalue일 때는

Lvalue일 때는 Lvalue자체가 값이 아니고 어떤 값이나 인스턴스를 가리키는 레퍼런스다.
때문에 대입 연산을 할 때 로컬에서 생성된 레퍼런스에 대해 복제를 해서 복제된 리소스를 이용해야 한다.
하지만 Rvalue일 때는 Rvalue 자체가 값이기 때문에 복제를 할 필요 없이 바로 대입해서 연산 속도를 빠르게 만들 수 있다.

일단 이렇게만 이해했는데 제대로 한건가 모르겠다. 다음에 필요하면 다시 이해해보자.

  • tuple<CTypes...> tuple_cat (Tuples&&... tpls)

    • 위의 코드에는 나와있지 않지만 tuple 두 개를 합쳐주는 역할이다.(string concatenation 같이)
    • Ex. (1, a, 2)와 (2, b, 3)을 파라미터로 넣으면 (1, a, 2, 2, b, 3)이 나옴
  • typename tuple_element< I, tuple<Types...> >::type& get(tuple<Types...>& tpl) noexcept
    typename tuple_element< I, tuple<Types...> >::type&& get(tuple<Types...>&& tpl) noexcept
    typename tuple_element< I, tuple<Types...> >::type const& get(const tuple<Types...>& tpl) noexcept

    • vector에서 operator[]의 역할을 대신한다.([]를 tuple에도 써봤는데 컴파일에러가 뜬다. tuple에서 []를 쓸바엔 vector를 써라 이런 느낌인 것 같다.)
    • Rvalue reference에 대해서도 오버로딩 되어있어 get<0>(mytuple)=1;과 같은 코드도 편하게 사용할 수 있다.
  • tuple<Types&...> tie (Types&... args) noexcept

    • tuple의 원소들을 각각 다른 변수에 한 번에 넣어준다.

    Ex.

    1
    2
    
    mytup=make_tuple(10, 20, 30);
    tie(a, b, c)=mytup;
    
  • tuple<Types&&...> forward_as_tuple (Types&&... args) noexcept

    • tuple타입을 파라미터로 넣어야할 때 make_tuple을 사용하지 않고 전달할 수 있게 해준다.
    • void print(tuple<int, string, int> tp)가 정의되어 있을 때,
      print(forward_as_tuple(1, string("asd"), 2))로 호출이 가능하게 해준다.

풀고나서

  • pair, string으로만 풀었을 때 180ms로 통과했고, tuple을 이용해서 풀었을 때 156ms로 통과했다.
  • 시간을 정확히 재보지 않아서 단정지을 수는 없지만 (아마도) pair을 다중으로 사용하는 것보다는 tuple이 더 빠른 것 같다. 앞으로 자주 써야겠다.

Leave a comment