はじめに
現在、モダンなC++(C++14以降、ギリC++11も含んでいいと思ってる)の開発では、様々な機能の追加により過去のC++では考えられないような、セキュアかつ高効率な開発が行えるようになっている。
組み込みのデバイスでは重すぎる等といった話も、何が問題になるのかをきちんと把握すれば怖い話ではない。
そういった環境の変化を受け入れずに、過去のC++にしがみついたり、勉強をしないのは最早怠慢である。
そういった人に送る言葉は一つである。
「おまえもしかしてまだ自分が(仕事があって)死なないとでも思ってるんじゃないかね」
ということで、モダンC++を使いましょう。
モダンC++とは
そもそもモダンC++とはなんなのか。
C++14以降、ギリC++11を含むと言いはしたが、モダンC++とは単にバージョンを指せばいいということではないと思っている。
というのも、機能が劇的に変化、追加されたものを使わないのであれば、それは最早モダンC++ではない。
いくらでも過去の危険で低効率な開発をすることになる。
何がモダンC++をモダンC++たらしめるのか
先に述べた過去の危険で低効率な開発の対極に位置する、させる機能が必須になると思う。
それはC++の大きな変更に起因するので、その中から特に重要になるものを挙げていく。
- スマートポインタ
- ラムダ
- 範囲for
- auto変数
- constexpr
- enum class
- 追加された各種標準ライブラリ
モダンC++な機能
スマートポインタ
モダンC++に限らず、モダンな開発には必須と言ってもいい。
これも標準ライブラリのうちだが、別に書くだけの意味がある程重要なライブラリ。
ただ、ここでいうスマートポインタとはauto_ptrではない。
unique_ptr、shared_ptr、week_ptrである。
何故auto_ptrでは駄目なのかというと、まず真っ先に出てくるのがそもそも既に非推奨の機能だからである。というか、これが全てと言ってもいいかもしれない。
非推奨となる理由は色々とあるだろうが、一番の問題は権限の管理の甘さにあると思っている。
基本的にはunique_ptrのようにし、最終的に誰が管理するものなのかをハッキリするべきだが、そういった管理になっていない。
これに付随して右辺値参照やムーブセマンティクスもあるが、そこまで書くとそれだけで記事を書き起こすレベルなので割愛。
ラムダ
可読性が上がる。便利。以上。
というのは些か投げやりすぎるのでちょっと…
最も多く使われるであろう用途は、スレッド内の処理だと思う。
これを、メソッドを作ってスレッドに渡すのでは、ちょっとした処理なんかは可読性が落ちるし、実装の手間もかかる。
そこでしか使わない処理を作る必要があるのであれば、ラムダを使って可読性を上げて手間も減らすことができる。
あと、メソッド名を考えなくて済む。
範囲for
コーディングの効率が上がる。
これは間違いない。
使えば分かるが、一度使うと元には戻れなくなる。
イテレーターへの理解も強制的に深まる。
更に言えば、カウンターの操作を誤ったり、配列へのアクセスを誤ったりすることがなくなる。
vector等の配列内全てに対して処理を行う場合には、範囲forを使うようにしてしまった方がいい。
auto変数
戻り値の型を意識せずにコーディングできるのは楽でいいし、コードを書く量が減る。
マジで減る。
テンプレート型の指定がなくなるので、書く量が減るし、あれもこれも直さないといけないというのも減る。
特にスマートポインタは記述量が増えがちなので、積極的に使っていきたい。
constexpr
constexprは定数を定義することができる。
マクロとは異なり副作用がなく、リテラルであれば関数だけでなくクラスも作ることができる。
C++11ではほぼマクロの置き換えのようなことしかできないが、C++14からは関数を書くように処理ができるようになり、かなり色々なことができるようになった。
ただ、当然マクロでしかできないこともあるが、純粋な文字列の置き換えになるマクロは定数としてではなく、まさしくマクロとしてだけ使えば良くなる。
enum class
enumだが、かなり型拘束の強いenum。
C言語のintで何となく数値を入れるというような、かなり適当な扱いができたenumに比べて、厳密な型指定とenum自体の型を指定できることで、厳密な方チェックが行えるようになった。
つまり、enum型を無視した値の設定のような問題がなくなる。
追加された各種標準ライブラリ
ライブラリなので、モダンとは?という感じだが、ゴリゴリ書かずにライブラリに頼るのはモダンだと思うので。
filesystem
環境依存のファイル操作のAPIが消える!神!
こいつの親戚(?)にstd::pathというのがあって、ファイルパスを+とか+/とか/とかでいい感じに整形してくれたりするのもいる。
もうファイルパスを整形するコードを書かなくていいんだ。
こんなに嬉しいことはない。
tuple
モダンな言語ではよくあるタプル。
構造体の作らなくても、複数の型をまとめたデータ型を作ることができる。
タプルってモダンだよねってだけで入れました。
chrono
時間の取得はほとんどシステムに依存していたが、C++標準でサポートされた。
C++11で追加された時点では、単純な時間を扱う程度でしか使えないので、結局システムのライブラリに頼らなければならない事があったが、C++20で一気に強化され、ほぼこれだけで済むようになった。
最後に
なんやかんやほとんどがC++11で追加された機能だが、ここで紹介したもの以外にも、if文での初期化や、各種ライブラリ・STLの追加により、どんどん便利かつセキュアなコーディングが可能になっていっている。
パフォーマンスが上がる改善が行われている場合もある。
是非、古いC++から脱却し、モダンC++で開発を進めていってほしい。
特に組み込み。
マイコンでモダンC++使わせてくれ。