なが月・14日目

帰宅後から開始。そろそろ忘れられているがタイトルの読み方はなつやすみがんばり月間なので「ながげつ」である。

C++ではデフォルト実引数を指定することも可能になった。関数プロトタイプ宣言をする場合は宣言部分でデフォルトを指定しておき、実装部分には書かない。コンパイラはプロトタイプ宣言だけを見て関数の引数がマッチするかを確認するので(Argument Dependent Lookupであろう)、実引数を欠いた呼び出しは同名の「引数をとらないプロトタイプ宣言」を探しに行き発見できずエラーとなる。デフォルト引数が宣言と実装の両方で指定されているとエラーになるらしいのだが、CMake+MinGW+g++のCLion(C++14)では平然とビルドが通った(宣言側のデフォルト引数が優先された)。

そしてC++ならではの機能として関数テンプレートがある。テンプレート関数を型T1, T2, ...を用いて(Tnと決まっているわけではなく変数名のように名付けられる)

template <typename T1, typename T2>
void myEcho(T1 a, T2 b){
cout << "First you said: " << a << " then: " << b << endl;
}

と定義しておき、呼び出すときにはmyEcho<int, string>(42, "mostly harmless");などとする。各変数に対して指定した型が実装中で行う処理に適合している限りはこれでコンパイルが通り正しく実行される。仮にcout << aのところをcout << a/2とすれば、T1は除算演算子が定義されている型でなければならないという制約が課せられると考えられる。実際この場合myEcho<string, string>("Answer to the Ultimate Question", "So long, and thanks for all the fish");はコンパイルエラーとなった。

ここまで書いていてふと思い出した。C#のDictionaryである。System.Collections.Generic.Dictionaryはvar myDict = new Dictionary<string, int>();などと書く。関数テンプレートと類似している。だがC#ジェネリッククラス内で算術演算子は使えないなど制約があり、C++ほどの柔軟性はないとマイクロソフトC#プログラミングガイドに記載がある。

アルバイト業務でも発見があった。ごく初歩的な話ではあるが、オブジェクト指向の使いどころである。一般に「たい焼き」やAnimal/Dogクラスに例えたオブジェクト指向の何たるか、や、実装の隠蔽といったメリットはよく目にするが、(プロジェクト全体でOOPを意識して実装しているというような外部的な要因ではない)具体的な要請を感じたのは初めてだった。

すなわち、同一クラスの中で似たような処理を二つ行う必要があるが、処理の制御構造が異なっており一つのメソッド内で場合分けをするのは適切ではなかった。しかし必要な引数は処理対象を除き共通であり、ほとんど同じ引数を与えて個別に(クラス)メソッドを呼んでいる状態が出来上がった。

それを見たとき、明らかにこれは無駄であり、クラスのプロパティに共通の要素を入れておけば各々で異なる要素だけを引数として与えればよい、そのためにクラスのインスタンスを作り共通部分を参照させることが適切だという考えに至った。メモリの潤沢な時代であるから値渡しで無駄になるメモリ領域は些末な問題だが、メソッドを増やすたび共通部分の引数をコピーペーストするのは看過しがたい非効率で、こうした場合にOOPが有用であると認識できたのだった(※継承によるコードの抽象定義―特化再利用の恩恵は、今回実装した外部と通信する単発的な処理にはあまり関係がなかった)。