C++スタイルのキャストを補助する。

hatedaraから投稿するとなんでかタイトルだけ文字化けしてしまうので、タイトルは付けないことにしました。なんでやろ。

さて、12月です。師走です。忘年会シーズンなので、一週間に一回は飲み会があります。懐が・・・orz。帰省のための新幹線代が非常に痛いです。

まぁそんなことはさておき、C++erな方々は、当然だとは思いますが、キャストをする時にはCスタイルのキャストではなく、C++スタイルのキャストを利用しているかと思います。
C++スタイルのキャストは、意味が明確になるのでいいんですが、いかんせんタイプ数が非常に多くなりがちです。↓こんな感じに。

C++スタイル:static_cast<CHoge>(hoge)
Cスタイル:  (CHoge)hoge

自分もC++を書いていて、基本的にはキャストはあまり利用しないんですが(しまくらなきゃいけない場合は設計が悪い場合が多いため)、warningの抑制のために、unsigned int とintを合わせんといかん、とかそういう場合に利用しています。
そんな時に一々static〜とかreinterpret〜とか打つのはめんどいので、以下のような関数を書いてみました。
これとkey-chordを合わせて、c++-mode-hook辺りに仕込んでおけば、一発でいけるようになります。

(defvar my-c++-cast-list '(("s" . "static_cast<%s>(%s)")
                           ("r" . "reinterpret_cast<%s>(%s)")
                           ("c" . "const_cast<%s>(%s)"))
  "C++ style cast and prefix key assoc")

(defun my-c++-cast-region (reg-min reg-max prefix)
  "リージョンで囲んだ領域に対してキャストを適用する。"
  (interactive "r\ncprefix : ")
  (my-c++-cast-internal reg-min reg-max prefix))

(defun my-c++-cast (prefix)
  "現在のシンボルに対してC++スタイルのキャストを適用する。"
  (interactive "cprefix : ")
  (let* ((symbol-pos (or (bounds-of-thing-at-point 'symbol)
                         (bounds-of-thing-at-point 'word))))
    (my-c++-cast-internal (car symbol-pos) (cdr symbol-pos) prefix)))

(defun my-c++-cast-internal (reg-min reg-max prefix)
  "実際にC++スタイルのキャストを行う関数"
  (let* ((symbol-atp (buffer-substring-no-properties reg-min reg-max))
         (type (read-from-minibuffer "Cast To Type : ")))
    (delete-region reg-min reg-max)
    (insert (format (cdr (assoc (char-to-string prefix) my-c++-cast-list))
                    type symbol-atp))
    ))

(add-hook c++-mode-hook (lambda () (key-chord-define c++-mode-map (kbd "r4") 'my-c++-cast)))

なんか既にこんな関数はありそうな気もしますが、まぁ習作代わりに。調べるより早い気もしますし。