Expressの有線LANカードリストaudio_visualblogdiydokuwikiemacsenetcfreebsdgadget電子工作lifehacklinuxMacmemonas4freenetworkpcPlayGroundprogramming勝手に翻訳wikiwindowsリンク履歴書この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。変更したい場合は管理者に連絡してください。新年明けましておめでとうございます(遅。開設14年目となるクソゲ~製作所を本年もよろしくお願い致します。C++のテンプレートには特殊化という、特定の型パラメータの時にテンプレートの実体を別に定義する機能がある。C#版テンプレートとも言えるジェネリックでは、なんということでしょう、特殊化が使えないではありませんか!それをどうにかしてジェネリック特殊化っぽい事をしてみたっていうお話。こんなコードがあったとする。''doc.FindChildren<SectionNode>()''は正しい挙動をするものの、''doc.FindChildren<TitleNode>()''の方は空のリストが帰ってくる。''FindChildren()''は''Node.Children''しか見てないので、独立したメンバ''SectionNode.Title''が入るはずはなく当然の挙動である。こんな時、C++なら特殊化で''FindChildren<TitleNode>''専用の処理が書け同一のインタフェースを提供できるのだが、前述の通りジェネリックは特殊化が使えないの。C#的には''FindChildTitleNodes()''的な別メソッドで提供するのが正しいのかもしれないが、やっぱり統一感に欠けて美しくない(そもそもこんな糞いデータ構造にすんなって話だが例ってことで許してね。知恵を振り絞って''FindChildren''を以下のようにした。元の''FindChildren()''を''FindChildrenInternal()''とし、''FindChildren()''には型パラメータ''T''に応じた処理を書くようにした。C++でコンパイラが自動で行ってくれる特殊化による処理の振り分けを、実行時に手動で行うような感じかしら。原理上、実行時コストは増えるが、この程度なら大した影響はないだろう。JIT様もあることだし。型が増えると''if''と特殊化処理の嵐になるが、型ごとに処理デリゲートを作って''Type''とデリゲート辞書でも作ればすっきりするので大した問題ではない。そもそも、そんな状況は最早「特殊化」の本質から外れてるので設計から見直すべきだろう。このコードのミソは(1)~(3)の部分。(1)で処理すべき''T''の型が明確になったものの、(2)-aで''List<T>''としているのはコンパイルを通すため。TitleNode''になるとは限らないので(2)-bで型不一致エラーになる。SectionNode''で呼び出した時にどうなるかを考えれば、すぐにおかしさに気づいて頂けるかなと。(3)も一見''titles.Add(e.Title)''で良さそうだが、これまた''TitleNode''が必ずしも''T''に変換可能とは限らないのでCS1503エラーとなる。よって、ちょっとアホくさいが''TitleNode''を自身の型''T''にキャストしてやらなければならない。メソッドの引数に型パラメータを持てる場面では、[[https://arbel.net/2007/11/22/c-partial-specialization-with-extension-methods/|拡張メソッドを使った特殊化もどき]]が使える模様。リフレクションは楽しいなー。C++にも軽量な型情報システムがあればいいのになぁ...。Decomo文書の表示以前のリビジョンメディアマネージャー文書の先頭へ。