2019-01-16-01-make_from_tupleの追加 - project-enigma

2019-01-16-01-make_from_tupleの追加

>> Site top >> weblog >> 月別アーカイブ >> 2019年01月のlog >> 2019-01-16-01-make_from_tupleの追加

最終更新日付:2019/01/16 07:35:31


make_from_tupleの追加

2019 年 01 月 16 日

C++17 で、make_from_tuple というのが追加された。tuple の内容をパラメータとしてコンストラクタを呼び出すものだ。

今回はその make_from_tuple を追加する対応。

‥‥‥というと簡単な話みたいだけど、思ったより面倒だった。問題は、stl:tuple の要素数が実行時でないと判明しないことだ。もちろん STL のstd::tuple はそうではないけれど、CL-STL ではそうだ。そして、CL-STL では new はマクロで、コンストラクタ呼び出しのパラメータをベタにその場所に展開する。この仕組みと、stl:tuple の要素数が実行時にしか判明しないという事情が、なんとも噛み合わないのだ。

幸い、new が型名から名前を生成するコンストラクタは、コンパイラマクロを伴う関数だ。だから、make_from_tuple をマクロにしてやれば、コンストラクタ関数名の生成まではマクロ展開の中でやってしまえる。しかしそこから先は実行時コストを負担しなければならない。まぁこれは CL-STL の性質を考えれば仕方ないだろう。

そんなわけで、ひとまず make_from_tuple は以下のようなマクロになった。コンパイル時点でコンストラクタ関数名を生成し、内部関数である __make_from_tuple-imp に tpl と共に渡すだけ。

#-(or cl-stl-0x98 cl-stl-0x11 cl-stl-0x14)
(defmacro make_from_tuple (type tpl)
  (let ((ctor-name (cl-overload::make-constructor-name type)))
    `(__make_from_tuple-imp #',ctor-name ,tpl)))

 

で、問題はその __make_from_tuple-imp 関数だ。これは、以前applyを捻り出した時に書いたのと同じ方法を使うしかなかった。つまり、ある程度一般的と思える数のパラメータについてはベタに展開して、それ以外は coerce でリストに変換して cl:apply、というわけだ。

#-(or cl-stl-0x98 cl-stl-0x11 cl-stl-0x14)
(locally (declare (optimize speed))
  (defun __make_from_tuple-imp (ctor tpl)
    (let ((arr (__inner-array tpl)))
      (declare (type simple-vector arr))
      (let ((cnt (length arr)))
        (declare (type fixnum cnt))
        (case cnt
          (2 (locally (declare (type (simple-vector 2) arr))
               (cl:funcall ctor (svref arr 0) (svref arr 1))))
          (3 (locally (declare (type (simple-vector 3) arr))
               (cl:funcall ctor (svref arr 0)
                                (svref arr 1) (svref arr 2))))
          ;;    :
          ;;    :
          ;;    :
          (8 (locally (declare (type (simple-vector 8) arr))
               (cl:funcall ctor (svref arr 0) (svref arr 1)
                                (svref arr 2) (svref arr 3)
                                (svref arr 4) (svref arr 5)
                                (svref arr 6) (svref arr 7))))
          (9 (locally (declare (type (simple-vector 9) arr))
               (cl:funcall ctor (svref arr 0) (svref arr 1)
                                (svref arr 2) (svref arr 3)
                                (svref arr 4) (svref arr 5)
                                (svref arr 6) (svref arr 7) (svref arr 8))))
          (t     (cl:apply ctor (coerce arr 'cl:list))))))))


 

実際には、make_from_tuple 自体を関数&コンパイラマクロ化してしまいたかった。しかし、色々試した結果(ひとまずは)断念。CommonLisp のリハビリ中だからなのかもしれない。そのうちまた試してみよう。

 

コメント

このページにコメントする

 

このページのタグ

Page tag : STLとその移植

Page tag : Common Lisp

 

 


Copyright(C) 2005-2019 project-enigma.
Generated by CL-PREFAB.