highlight

2016年3月21日月曜日

変数テンプレートでコンパイラのバグに遭遇した

変数テンプレートを使った時、コンパイラのバグに遭遇したので記載する。エラーに遭遇した時のコードとは別のコードを書き下ろしている。


// 変数テンプレートを持つクラス
struct Foo {
  template <typename Tp>
  static constexpr Tp var{0};
};

// それを持つクラステンプレートを定義し、
template <typename VTp, typename T>
struct Bar {
  static constexpr auto Var = VTp::template var<T>; 
};

int main(int argc __attribute__((unused)),
         char *argv[] __attribute__((unused))) {
  // インスタンス化する
  int x = Bar<Foo, int>::Var;
  return 0;
}

これを g++ でコンパイルしてみた。(行番号は上のコードとは対応してません)


templ_var.cc: In instantiation of ‘constexpr const auto Bar<Foo, int>::Var’:
templ_var.cc:10:25:   required from ‘struct Bar<Foo, int>’
templ_var.cc:15:24:   required from here
templ_var.cc:10:25: error: ‘template<class Tp> constexpr const Tp Foo::var<Tp>’ is not a function template
   static constexpr auto Var = VTp::template var<T>; 
                         ^
templ_var.cc:10:25: error: ‘var<T>’ is not a member of ‘Foo’

文法的には正しいハズなんだがなと思いつつも g++ はエラーを報告してくる。それにしても "is not a function template" って云うてるけどこれ関数ちゃうし、と思って、clang 3.7 で試してみるとコンパイルは通って、想定した結果が得られた。 Stackoverflow でも同様の話題が投稿されており、このスレッドのコメントで g++, clang プロジェクト宛のバグレポートもあげられているようだ。 clang では最近修正されたが、g++5.0.2 の現時点では修正される気配は無い模様。

g++ でも動くようにするには、変数テンプレートを使う方で、内部クラスを作ってその中で使えばエラーは回避できるようだ。詳しくは上のスレッドに投稿されているレスで。

2016年3月16日水曜日

emacs から pre タグ内へ paste

blog にコードを貼り付けるとき、別のファイルからテキストをコピーして pre タグ内へ貼り付けている。html や xml ファイルをまるごと自分で書く場合には、<![CDATA[....]]> でくくれば良いが、少なくともここの blog のフォームからの投稿時にはそれが使えないようだった。

C++ の template のように、< や > を使いまくるテキストを投稿するためには、いちいち実体参照表記に変換してやる必要がある。テキストをフォームに貼り付けたら、この変換をやってくれる親切なページがあるが、それでもその操作が段々億劫になってくる。

幸いにも私が使うテキストエディタは emacs なので、テキストを選択してコマンドを実行したら、クリップボードに実体参照変換済みのテキストが乗っている、というようなコマンドは作れそうだ。


(defun copy-html-pre-tag-escaped (&optional st en)
  (interactive "r")
  "Copy text in the region. and replace meta characters for html pre tag."
  (kill-new
   (replace-regexp-in-string
    "<" "&lt;"
    (replace-regexp-in-string
     ">" "&gt;"
     (replace-regexp-in-string
      "&" "&amp;"
      (buffer-substring-no-properties st en)))))
  )

文字列置換は別に正規表現で無くていいと思ったが、それらしい関数が探しきれなかった。 使い方はリージョンを選択してこのコマンドを呼ぶ(M-x copy-html-pre-tag-escaped)だけ。 実体参照変換後の文字列がクリップボードに乗っているので、それを paste すれば良い。

一応説明を書いておくと、buffer-substring-no-properties でリージョンにあるテキストを取得して、三種類の文字を対象に文字列変換する。 それを kill-new という物騒な名前の関数に渡せば kill-ring に入ると同時にクリップボードにもコピーされているという仕組み。

ググっている内に複数文字列を一挙に変換する関数をパッケージとして公開しているページを見つけた。面白そうなページなので、後でじっくり読んでみよう。

2016年3月10日木曜日

include guard 用文字列を uuid にして elisp で自動挿入

OSDN の wordpress にお世話になってたが、highlight.js の使い方がわからず、こっちに移行しようと思う。 highlight のテストがてら、あちらでの投稿をこちらに再投稿する。

boost のヘッダファイルを見ていると、include guard 用のシンボルが UUID_xxxxx... という感じにしてあるのに気づいた。 なるほど。これは確かに uuid を使った方が #define [ファイル名] なんかよりも合理的に思える。 これは真似したいなと思うが、ヘッダファイルを新規作成する度に、uuidgen した文字列を sed s/-/_/g してコピーしてソースに貼り付け、とか考えると明らかに面倒だ。 じゃあ、emacs lisp で自動化してやろうか、と思って書いたのが以下の lisp コード。

boost のヘッダファイルを見ていると、include guard 用のシンボルが UUID_xxxxx... という感じにしてあるのに気づいた。 なるほど。これは確かに uuid を使った方が #define [ファイル名] なんかよりも合理的に思える。 これは真似したいなと思うが、ヘッダファイルを新規作成する度に、uuidgen した文字列を sed s/-/_/g してコピーしてソースに貼り付け、とか考えると明らかに面倒だ。 じゃあ、emacs lisp で自動化してやろうか、と思って書いたのが以下の lisp コード。


(defun insert-random-uuid ()
 (interactive)
 "Inserts a UUID string suitable to CPP identifier"
 (shell-command "echo UUID_$(uuidgen | tr a-z\- A-Z\_)" t))

(defun insert-include-guard ()
 (interactive)
 "Inserts C/C++ header include guard."
 (progn
  (insert "#if !defined(")
  (insert-random-uuid)
  (let (p1 p2)
   (setq p1 (point))
   (end-of-line)
   (setq p2 (point))
   (kill-ring-save p1 p2))
  (insert ")\n#define ")
  (yank)
  (insert "\n#endif /* ")
  (yank)
  (insert " */")
  (beginning-of-line)
  (open-line 3)
  (forward-line)
  ))

これが eval された後、emacs で M-x insert-include-guard すると、


#if !defined(UUID_364889E3_11A2_493E_B861_5C20F63968D8)
#define UUID_364889E3_11A2_493E_B861_5C20F63968D8

#endif /* UUID_364889E3_11A2_493E_B861_5C20F63968D8 */

というような感じのテキストが自動挿入される。