概要
C++11以降に追加された機能にTupleがあります。
これはPythonなどのプログラミング言語でおなじみなのですが、TupleによってC++でもPythonのような書き方ができるようになりました。
関数の複数戻り値
# include <iostream>
# include <tuple>
std::tuple<int, int> add_and_sub(int a, int b)
{
return {a + b, a - b};
}
int main()
{
auto [aa, bb] = add_and_sub(20, 10);
std::cout << aa << " " << bb << std::endl;
return 0;
}
表示は 30 10
となります。Tupleを使用することで複数の戻り値を返すことができます。そしてそれを構造化束縛を用いて複数の変数で受け取るという流れです。Pythonで書けば以下のようになります。
def add_and_sub(a, b):
return (a + b, a - b)
aa, bb = add_and_sub(20, 10)
範囲for
# include <iostream>
# include <tuple>
# include <vector>
int main()
{
std::vector<std::tuple<int, int>> v{
{10, 20},
{2, 2},
{4, 1}
};
for (auto [aa, bb] : v){
std::cout << aa << " " << bb << std::endl;
}
return 0;
}
構造化束縛は範囲forとも相性が抜群です。TupleのVectorに対するループは上記のように書けます。Pythonで書くと以下のようになります。
v = [(10, 20), (2, 2), (4, 1)]
for (aa, bb) in v:
print(aa, bb)
構造体のソート
C++のTupleはPythonのと同様にprimitive型のみを含んでいればそのままソートすることができます。これを利用することで構造体のソートロジックを簡単に実装することができます。またラムダ関数とも相性が抜群です。
# include <algorithm>
# include <iostream>
# include <string>
# include <tuple>
# include <vector>
struct Data
{
int a;
int b;
};
int main()
{
std::vector<Data> v{
{5, 6},
{1, 2},
{3, 4}
};
std::sort(v.begin(), v.end(), [](const auto &lhs, const auto &rhs){
auto lt = std::make_tuple(lhs.a, lhs.b);
auto rt = std::make_tuple(rhs.a, rhs.b);
return lt < rt;
});
for (auto [aa, bb] : v){
std::cout << "Data[" << aa << "," << bb << "]" << std::endl;
}
return 0;
}
そう、実は構造化束縛はTuple以外の構造体にも使えるんです。Pythonで書くとこう。
import dataclasses
@dataclasses.dataclass
class Data:
a: int
b: int
v = [
Data(5, 6),
Data(1, 2),
Data(3, 4)
]
v.sort(key=lambda d: (d.a, d.b))
for d in v:
print(d)
auto, Tuple, 構造体束縛, 範囲for, lambda関数などをうまく使えばC++もPythonと同様に簡単に書けますね!