【自分用メモ】C++競プロ用便利コード

C/C++には「プリプロセッサ命令」などの機能があり，これら活用するとコーディングがかなり便利になります．
競プロに限ってですが，プリプロセッサ命令などを最大限活用したC++は，Pythonと同じか，より書きやすいように感じます．

## 提出時だけ出力されないデバッグ出力
変数の中身を確認しながらコーディングを進めたい時，逐一変数を標準出力するようなコード（デバッグ出力）を組むと思います．しかしこの方法だと，提出する時に，デバッグ出力を全てコメントアウトしなければならず，手間になります．

```c++
#define DEBUG
#ifdef DEBUG
#define dcout cout
#else
#define dcout  \
    if (false) \
    cout
int main()
{
    dcout << "Print only when debugging" << endl;
}
```

作られたマクロ`dcout`は`cout`と同じ文法で扱うことができ，デフォルトでは標準出力もなされます．しかし，1行目をコメントアウトするだけで，`dcout`は標準出力をしなくなります．
```diff_c
- #define DEBUG
+ //#define DEBUG
```
`dcout`を使ってデバッグ出力をしておきます．そして，提出する時に1行目だけコメントアウトすれば，`DEBUG`が非定義となり，`dcout`は何もしないマクロになります．

<details><summary>問題点</summary>
コメントでのご指摘の通り，これには少し問題点があります．例えば次のような例だと，`DEBUG`が定義されているか否かで振る舞いが変わってしまいます．

```c++
int main()
{
    if (0)
        dcout << "Hello" << endl;
    else
        cout << "World" << endl;
}
```
このような状態を"dangling else"といいます．

</details>


## `変数=変数内容`という形式でデバッグ出力
デバッグ時，`変数名=変数内容`という形式でデバッグ出力をしたい時があります．しかし，C++だとかなり面倒くさいです．
```c++
dcout << "counter=" << counter << endl;
```
そこで作るのが次のマクロ．
```c++
#define view(x) #x "=" << x
```
次のように使います．
```c++
dcout << view(counter) << endl;
// counter=10
```
このマクロでは，「文字列化演算子」というプリプロセッサ文法を使用しています．これは，変数名を文字列にする機能です．詳細は[Microsoft Learnを参照](https://learn.microsoft.com/ja-jp/cpp/preprocessor/stringizing-operator-hash?view=msvc-170)してください．

こういったほんの少しのコーディングの効率化が嬉しいのですよ🍰

<details><summary>ちなみに，Pythonだとかなり便利な文法が存在します．</summary>

```python:Python
print(f"{counter=}"}
```
</details>

## 標準出力に色を付けて見やすく
標準出力に特定の文字列を送ることで，文字に色を付けることができます．これを使って，先ほどの`view`をさらに見やすくします．
```c++
#define NC "\e[0m"
#define RED "\e[0;31m"
#define GRN "\e[0;32m"
#define CYN "\e[0;36m"
#define view(x) #x "=" CYN << x << NC " "
```
```c++
int main()
{
    int count = 3838;
    dcout << view(count) << endl;
}
```
こうすると，以下のように出てきます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/4e700b78-2646-27f5-5e36-114dea82d19b.png)
データの内容だけ青色で表示されました．些細な工夫ですけれど，これだけでもかなり見やすくなります．

## `for`に関するショートカット構文
$N$回ループを回す系の`for`構文は長ったらしくて面倒なので，これも効率化しちゃいます．
```c++
#define forrange(i, i0, I) for (int i = i0; i < I; i++)
#define rep(I) forrange(__counter, 0, I)
```

## ベクトルと行列
`std::vector`を使ってベクトルと行列を作ることが多々あります．特に，中身が`int`型になることも多いです．なので，これらの型を呼び出すショートカットを作成します．
```c++
template <typename T>
using Vec = vector<T>;
using IntVec = Vec<int>;
template <typename T>
using Mat = Vec<Vec<T>>;
using IntMat = Mat<int>;
```

## ベクトルと行列のデバッグ出力
`for`を用いてベクトルや行列の要素を逐一デバッグ出力するのは面倒臭いし，その上，提出時に無駄なforループが残ることになります（最適コンパイルとかすると自動的に取り除かれたりする？？🤔）．
なので，ベクトルや行列のデバッグ出力も専用のマクロを作ります．
```c++
#ifdef DEBUG
#define viewvec(vec)          \
    {                         \
        cout << CYN;          \
        for (auto x : vec)    \
            cout << x << " "; \
        cout << NC << endl;   \
    }
#define viewmat(mat)     \
    for (auto vec : mat) \
    {                    \
        viewvec(vec)     \
    }
#else
#define viewvec(vec) 0
#define viewmat(mat) 0
#endif
```
提出時，つまり`DEBUG`を非定義にすると，両者のマクロとも何もしないマクロになります．

## 行通過を知らせるやつ
いつその行を処理が通過するかを出力するマクロ`mark`を作ります．
```c++
#ifdef DEBUG

#define mark dcout << RED << "●" << __LINE__ << NC << endl

#else
#define mark 0
#endif
```
こういうコードを書いていたとします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/c09a2485-da8b-f08f-5d1a-63c691cc30b2.png)
すると，次のような出力が得られます．100行目を通過すると，赤文字で教えてくれます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/0355c5da-dd5f-9d90-c595-fbd847cfcb5e.png)
このマクロでは，`__LINE__`という定義済みマクロを使用しています．これは，ソースコードの行数を伝えるものです．[Microsoft Learnを参照](https://learn.microsoft.com/ja-jp/cpp/preprocessor/predefined-macros?view=msvc-170)してください．

## `np.ones`，`np.zeros`みたいなやつ
指定された長さのベクトルや，指定されたサイズの行列を作るメソッドです．
```c++
template <typename T>
Vec<T> filledvec(int size, T element)
{
    Vec<T> vec;
    rep(size) vec.push_back(element);
    return vec;
}

Mat<T> filledmat(int height, int width, T element)
{
    Mat<T> mat;
    rep(height) mat.push_back(filledvec(width, element));
    return mat;
}
```

## 全ソース
https://gist.github.com/Mya-Mya/fdcca479041fdd6f36612b07348a211d