2022年6月30日

C/C++ の簡易パッケージマネージャを作った話

概要
    ある程度大きなソフトウェアを開発するには, ソフトウェアを機能ごとにモジュール化して, 機能ごとに開発すると,効率的に分業できる. また,インターフェースに互換性があれば, 複数ライブラリをベンチマークして, 機能ごとに最もユースケースに合うライブラリを利用することもできる.
  パッケージ管理において Python は非常に参考になる言語で, 例えば,requirements.txt にインストールしたいライブラリとバージョンを記載して pip を実行すれば,ものの数分で環境が構築できる. しかも,venv などを利用すれば仮想環境として構築できるため, 同じ PC の中に複数プロジェクト向けの環境を用意できる. こうした仕組みは是非とも C++ にも欲しい.
    既存の C++ 向けパッケージマネージャーもあるが,なぜか pip でのインストールが必要だったり,デファクトスタンダードというレベルのものはないため, C/C++ 向けの簡易パッケージマネージャーを試しに開発してみることにした.

※ C++ で既存のパッケージマネージャーとしては ConanVcpkg, Hunter, Buckaroo, poac などがある.ここで紹介するのは,趣味で作ったおもちゃの(プロダクトレベルでない)パッケージマネージャーなので,本格的に利用する場合は,よくよく各パッケージマネージャーを比較検討することをお勧めする.
※ 2013 年以降,docker の登場により,C++ の環境としても構築しやすくなってはいるが, docker の主眼は(パッケージ管理ではなく)環境そのものの仮想化なので,別の問題として考える.

2022年5月28日

C++ で複数の std::vector<T> を1つの std::vector<T> を基準にソートする

概要
  C++ で複数の std::vector<T> を1つの std::vector<T> を基準に sort する場合を考える ※1. こうした場合,通常 std::vector<T> に含まれる値を構造体や,std::pair<T>, std::tuple<T> に入れ替えてから std::sort() で並び替える. ここで,sort された結果を,構造体や,std::pair<T>, std::tuple<T> のまま取り扱いたい場合は問題ない. 一方で,構造体や,std::pair<T>, std::tuple<T> を,再び std::vector<T> に変換したい場合は, データ構造ごとに別々の実装が必要でコードは煩雑となり,計算コストも増える.
  この計算コスト削減の観点では, 基準となる std::vector<T> の sort 順序を保存しておき, 保存結果を元に残る std::vector<T> する方法が考えられる. この考えは,例えば Stack overflow で取り上げられている ※2.
  この投稿では,計算コストを加味した上で,さらにコードを簡略化する方法を紹介する. C++ のテンプレートの再帰展開を応用すると,これまで煩雑だった処理を1行で記述できるようになる.

※1. 具体例としては,一方の std::vector<T> が ID を持っており,もう一方の std::vector<T> が対応する文字列を持っている場合に, ID を基準として 2 つの std::vector<T> を並び替えたい状況が考えられる.
※2. 例えば,StackOverflow に紹介されている. Sorting multiple vectors based on a reference vector