トップ画像
競プロ環境構築#2 C/C++編

執筆者: 終に鮭

最終更新: 2021/03/17

2021年アクセスランキング:2位

共通編の続きです。 WSLを導入したWindows10、またはMac OSやLinuxなどのUNIX系OSを前提にしています。 Ubuntuなどの仮想マシンが使えるならばこの限りではありません。

C++はどのような言語か

C言語は説明するまでもないかと思うのでC++だけ。
C++は実行速度が速く、開発でも比較的よく使われる言語です。 イテレータや参照[1]によりポインタの操作がユーザーから秘匿されたり、クラスやテンプレートなどオブジェクト指向のパラダイムが持ち込まれたりして、C言語と比べて書きやすくなっています。 C言語との互換性が非常に高く、ポインタを直接操作することもでき、低級言語として扱うこともできます。
[1] int&型などのことです。関数にint*型で渡して関数内部で間接参照する、などとしなくても良くなっています。
2021年現在の競技プログラミング界隈では、事実上C++が標準語のようになっています。 AtCoderでは多くの言語を使うことができますが、他のコンテストサイトではあまり言語が多くなかったりします。 その中でもC++とJavaは標準的で、C++のほうが速いからか情報も多いです。 [独自研究?] そのため、競技プログラミングをするならC++は初心者におすすめの言語といえます。
C言語の環境構築もほぼ同じなので一緒に解説しますが、おまけ程度にしておきます。私は初心者がC言語を使うことはおすすめしません これはC言語しか習っていないうちの学生にも当てはまることなので、ぜひC++を使ってください。 一部の文法はC言語と似てるけど、便利機能モリモリで書きやすくて良いですよ。 はっきり言って、公式ガイドで環境構築できないくらいのスキルしか無いのであればC++に移行すべきだと思っています。

コンパイラ選び

C++のコンパイラには主に以下の3つがあります。

GCC

GNU Compiler Collectionの一部、GNU C++ Compiler。そのコマンド名g++からそのままg++と通称されます。
大抵のLinux OSは多くのGNUソフトウェアを標準インストールしており(GNU/Linuxの思想)、 GCC(ただしここではGNU C Compilerのこと)もそのうちに含まれています。
多くのLinuxユーザーはGNU C Compilerに馴染みがあるはずであり、GNU C++ Compilerはそれとほとんど同じオプションを利用することができます。
競プロer的に嬉しいのが、libstdc++のすべてのヘッダを読み込むbits/stdc++.hヘッダがあることです。 関数ごとにいちいちincludeディレクティブを書かなくていいことは記述速度最優先の競プロではプラスに働きます。 ただし実務で使うとブチ切れられることがあるらしいので気をつけてください。
多くの競プロerがGCCを使っており、なんやかんや一番おすすめです。

Clang

LLVMコンパイラ基盤の一部で、C、C++、Objective-C、Objective-C++の4言語のコンパイラ群です。
Macでは標準がClangらしいですね。他のことは何も知りません。
自分のPCにすでにClangが入っているか、GNUが嫌いでなければ特に使う理由はないと思います。

VC++

Microsoftが開発しているC++コンパイラですが、簡単に探した限りネイティブLinuxで使えるという情報は一切見つかりませんでした。当然ながらAtCoderでも対応はなし。

その他

Intel C++ CompilerやAMD Optimizing C++ Compiler、NVIDIA HPC SDK Compilersなどのプロセッサに最適化されたコンパイラ。当然競プロで使われることはまずない。

コンパイラのインストール

WSL Ubuntu 20.04では必要ありません。gccもg++もGCC 9が標準搭載。やったぜ。
今後AtCoderで言語アップデートが入ってGCC 10になったときのためにインストール手順を書いておきます。
完璧にAtCoderと同じ環境にしたい場合はBoostが必要になりますが、私は使っていないのでここでは紹介しません。

C++

忙しい人向け

sudo apt install g++-9

複数バージョンの管理もしたい人向け

# パッケージのインストール
sudo apt install g++-9

# ここから蛇足

# シンボリックリンクの書き換え
# 今回はalternativesというバージョン切り替えツールを利用する
# g++が設定済みでないことをチェック
update-alternatives --config g++
# update-alternatives: error: no alternatives for g++
# とか出ればOK
# そうでないものが出たらそのままEnterを押す

# g++にalternativesの設定を追加
# これをすると/usr/bin/g++ -> /etc/alternatives/g++ -> /usr/bin/g++-9のようなシンボリックリンクが張られる
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 5

g++ --version

# g++10をインストール
sudo apt install g++-10

# 優先度10なので、こちらのほうが優先度が高くなる
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10

g++ --version

# マニュアルモードでバージョンを戻しておく
sudo update-alternatives --config g++

C言語

alternativesの部分はg++を全部gccに書き換えればいいだけなので省略します。

sudo apt install gcc-9


コンパイラの使い方

AtCoderのコンテストのルールのページを見ればコマンドが書いてあります。
https://atcoder.jp/contests/abc194/rules より引用。

g++ -std=gnu++17 -Wall -Wextra -O2 -DONLINE_JUDGE -I/opt/boost/gcc/include -L/opt/boost/gcc/lib -I/opt/ac-library -o ./a.out ./Main.cpp

オプションの説明

  • g++:コンパイラ本体です
  • -std=gnu++17:C++のバージョンを指定します
  • -Wall:標準的な警告をすべて出します
  • -Wextra:その他の警告をいっぱい出します
  • -O2:レベル2でコンパイル時最適化します
  • -DONLINE_JUDGE:ちょっとややこしいので後述
  • -I/opt/boost/gcc/include:Boostを#include<>の検索対象に含めます
  • -L/opt/boost/gcc/lib:よくわからん
  • -I/opt/ac-library:AtCoder Libraryを#include<>の検索対象に含めます
  • -o ./a.out:出力ファイル名を./a.outにします
  • ./Main.cpp:入力ファイル名です

Dオプション

-DHOGE=FUGAは入力ファイルの先頭に#define HOGE FUGAとするのと同じ効果を持ちます。 FUGAが省略され-DHOGEと書かれた場合、#define HOGE "1"とするのと同じ効果を持ちます。 Includeガードでよくやるやつですね。

AtCoder Libraryを導入する

AtCoder Libraryは AtCoderのジャッジで利用することができるオープンソースなC++ライブラリです (つまりC言語は対象外、移植は様々な言語にあります。 C言語版はここ。 アクティブなプロジェクトで、C++ STLのデータ構造(setmap等)も移植対象とするようなので、 C言語使いの皆さん、是非プルリク出してあげてください)。 一般的な開発にはあまり使われない、しかし競技プログラミングでは重宝されるような機能が多数備わっています。
具体的には

  • modint
  • UnionFind
  • Segtree
  • LazySegtree
  • maxflow
  • mincostflow

などが含まれます(その他にも多数あります)。

ダウンロードとインストール

ここのGitHubリポジトリからダウンロードしてきます。 zipファイルをダウンロードして解凍してもよいのですが、 WSL Ubuntuにはunzipはデフォルトで入っていないようなのでgit cloneでダウンロードすることにします。なぜgitはデフォルトで入ってるんだろう。使うからええんやけどさ

# /opt下にダウンロード
cd /opt
sudo git clone https://github.com/atcoder/ac-library.git

# インクルードできるかチェック
g++ -I/opt/ac-library ./acl_include.cpp

acl_include.cppの中身

#include <atcoder/all>

int main() {
	return 0;
}

以上。
毎回-Iオプションを付けるのが面倒な方は、環境変数CPLUS_INCLUDE_PATHにパスを付け足せばよいです。
.bash_profile

export CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:/opt/ac-library"

# .bash_profileを書くと.bashrcが読まれなくなるので、こっちから読み込むように指示
source ~/.bashrc

適用できたか確認

source ~/.bash_profile
g++ acl_include.cpp


エイリアスを設定する

-Iオプションを付けるのが面倒な方は~、なんて言いましたが、どちらにせよ-std=gnu++17などのオプションはつけるべきです。 しかし面倒くさい。そのためのエイリアス。
.bash_aliasesにでも次のように付け足しましょう

alias g++-ac='g++ -std=gnu++17 -Wall -Wextra -O2'

とりあえずこれだけあれば十分かなと思いますが、好みに応じて増やしたり減らしたりしてください。

テンプレートの作成

atcoder-cliのテンプレートに設定しておくとよいです。 私はこれで十分だと思っていますが、extgcdやdijkstraなど、ライブラリを付けたい方は付けてください。

#include <bits/stdc++.h>
#include <atcoder/all>

using namespace std;
// using namespace atcoder;
using ll = long long;
const ll MOD = 1000000007LL;
// const ll MOD = 998244353LL;

const vector<pair<int, int>> dpos4 = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
// const vector<pair<int, int>> dpos8 = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	return 0;
}


stdc++.hのプリコンパイル

bits/stdc++.hを使うとコンパイル速度はかなり落ちます。 何度もテストする場合、それぞれの機能ごとに逐一includeしたほうが良いかもしれません。 少なくとも、手元環境で使う場合はプリコンパイルしておきましょう

# sudoをエイリアスで書き換えるというヤバいことをするので新しいシェルに入る
bash

# エイリアスの末尾がホワイトスペースのとき、次のトークンがエイリアスかチェックするらしい
# g++-acエイリアスを使わない場合はこれをする必要はない
# CPLUS_INCLUDE_PATHを設定済みの場合-Eオプション(環境変数を引き継ぐ)は必須
# 参考:https://qiita.com/homines22/items/ba1a6d03df85e65fc85a
alias sudo='sudo -E '

# 本体部分
for header in `find /usr -type f -name 'stdc++.h'`; do
	sudo g++-ac $header
done

# 立ち上げたシェルから抜ける
exit

# PCHが生成されたことを確認
find /usr -type f -name 'stdc++.h.gch'


次回予告

次回はPythonです。こちらで検証に成功すればnumbaの導入までやりたいですね。

取得に失敗しました

2020年度 入部

Twitter GitHub YouTube