3匹の猫

みみねこの競プロ精進メモ

【C++】chmin(), chmax() は1行で書けるか?

オンライン授業ってリアルタイムで出席する必要ある?(愚痴)





事の発端

以下は競プロの話である。

.clang_formatによる自動フォーマットの設定を弄っていて、
AllowShortFunctionsOnASingleLine: All
とかの設定をすることで、短い関数をそのまま改行せず1行で表示することが出来る。if文やfor文なども似たような設定をすることで、1行表示ができる。

短い関数というのはつまり、戻り値がある関数の場合『return文だけで構成される』ということで、例えばif文を使ってchminを書いてしまうと、

template<typename T> inline bool chmin(T &a, T b) {if(a<b){a=b;return true;}return false;}

と表示したいところが、フォーマットすると

template<typename T> inline bool chmin(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

という風に改行されてしまう。競プロをやるうえで非常に見づらいし、chminごときに7行も使ってられない。

chmin(), chmax()でやりたい処理

上の関数を見ればわかるのだが、chminの場合、

  • aは参照渡し、bは値渡しで受け取る
  • もしaと比べてbの方が小さいならaにbを代入してaを更新し、trueを返す
  • そうでないならなにもせず、falseを返す

という処理をしている。chmaxの場合はchminの不等号の向きをひっくり返すだけである。

条件演算子

if文の使用目的が「aよりbの方が小さい(大きい)か?」だけなので、条件演算子を使って書き直せそうである。条件演算子とは、

条件 ? 真のときの返却値 : 偽のときの返却値

という風に条件によって返す値が変わるようなときに使える便利な演算子である。三項演算子と言った方が馴染みがあるかもしれない。
chminでは、aとbの大小により返り値が変わるので、

return (a>b ? true : false);

と一行で書ける。ただこれだけだと、条件が真の場合にaにbを代入するという処理が書けない。trueを返す前に処理をしたいが、

return (a>b ? a=b; true : false);

とすると「ハテナがあるのにコロンがないよw」と言われてしまう。セミコロンを打たずに文を実行する方法は無いものだろのか?

コンマ演算子

コンマ演算子というものがある。

左辺, 右辺

という風に、本当に二つの式をコンマで並べて書くだけである。左辺の式を実行してから右辺の式を実行するが、この時の式の値(返り値)は右辺の式によって決まる。つまり、左辺の式の返り値は完全に無視されるということだ。この演算子で式をまとめることで、aにbを代入してからtrueを返すという処理が一行で書ける!やったね!

結論

以下のように書けば良い。

template<typename T> inline bool chmax(T &a, T b) { return ((a < b) ? (a = b, true) : (false)); }
template<typename T> inline bool chmin(T &a, T b) { return ((a > b) ? (a = b, true) : (false)); }

参考文献

はてな記法一覧 - はてなブログ ヘルプ
ソースコードを貼りつける方法を毎回忘れています。

三項演算子は悪か? - Qiita
タイトル通りです。競プロ以外で条件演算子を使うときは注意しましょうという話。

その他の演算子 - cppreference.com
演算子で良いのが無いか探してたらここで見つけました。