2010年11月28日

Boost.PreprocessorのData Typesについて簡単にまとめてみる

どうにも同じようなC++コードを延々書かなければいけない→プリプロセサが在るじゃない!
という事で、C/C++でメタプログラミングをこなす為のライブラリであるBoost.Preprocessorに手を出した。

リファレンスはググったら簡単に見つかった

4つの型

さて、Boost.Preprocessorには4つの型が存在するようだ。全てマクロアーギュメントを複数格納するコンテナらしい。

オンラインリファレンスと、偶然図書館から借りていたC++テンプレートメタプログラミング(以下、単に『書籍』と表記)の付録Aを元にまとめてみる。同書籍に記述されている型名も括弧で囲って併記している。

sequences (列)

(a)(b)(c)のような、()で囲ったマクロアーギュメントの連続。

書籍によると、このライブラリのデータ構造の中で最も効率的で、最も柔軟性に富み、かつ最も使いやすいものであるとある。

要素数に制限無し。ただし、引数に数値を取るマクロでは256以下の値しか機能しない。尤も、BOOST_PP_SEQ_SUBSEQがあるし、それほど問題にはならないんじゃないだろうか?

tuples (タプル)

(a,b,c)のような、()の中でマクロアーギュメントを,で区切って記述したもの。

ランダムアクセスなど、いくつかの基本的な操作が用意されているらしいが、マクロの数も少なく(後述)、それ程実用的とは思えない……

関数やマクロの引数記述部分と同じ書き方というのが利点だろうか?

また、このデータ構造を操作する全てのマクロには、必ずtupleの要素数を指定しなければならない。つまりそれは、tupleの要素数を計算する方法がない、という事だろう。
arrays (配列)

(3, (a, b, c))のような、要素数と要素のtupleで構成されたもの。tupleの亜種と言えそうだ。

tupleと異なり、データ構造中にサイズを持つ

lists (リスト)

(a, (b, (c, BOOST_PP_NIL)))のような、『先頭要素とそれ以降のlist』で構成されたtuple亜種。終端にはBOOST_PP_NILを用いる必要がある。

LispのS式のように()の嵐になりそう。

これも、長さの制限は存在しない。

書籍によると、他の構造に比べて操作が遅くなりがちで、読みにくくなりがちなので、普通、最後の拠り所としてしか使われないとある。が、実はこのデータ構造を操作するマクロが一番多い(後述)。

データ構造中、或いはそれを扱うマクロの引数として、そのサイズが必要となるのがtuplesとarrays。それはつまり、自作マクロの引数としての利用は現実的ではないということだろう。その逆がsequencesとlists。

tuplesが一番C/C++の記述に近い。エディタ上での自動インデントの誤動作も少なくすみそう。これで、サイズを求める事さえ出来れば最高なのだが……

各型で可能な処理

……うーん、やっぱりよく分からない。いや表記の違いはよく分かったが、それぞれどういう時に使うのかがハッキリしない。

例えば、STL連接コンテナのvectorlistは違いがハッキリ分かる。vectorは要素の参照が素早く行える、listは要素の追加削除が容易。

Boost.Preprocessorの4つの型も、それぞれ何らかの長所短所がある筈だ。そうでなければ1つの型で充分な筈だし。

そこら辺をハッキリさせる為に、各型の操作を行うマクロをまとめてみた。『特定の操作を行うマクロが多ければ、その型はそれが得意と言う事だろう』という理屈。一つ一つ確認する余裕はないので、同じ名前のマクロは別の型を対象としていても同じ操作を提供する物と仮定。

arrays lists sequences tuples
マクロ数 16 44 36 7
BOOST_PP_ ~
LIST_APPEND


LIST_APPEND_D


LIST_AT


LIST_AT_D


LIST_CAT SEQ_CAT

LIST_CAT_D



SEQ_CAT_S

LIST_CONS*

ARRAY_DATA





TUPLE_EAT
ARRAY_ELEM
SEQ_ELEM TUPLE_ELEM

LIST_ENUM SEQ_ENUM

LIST_ENUM_R


LIST_FILTER SEQ_FILTER

LIST_FILTER_D



SEQ_FILTER_S

LIST_FIRST


LIST_FIRST_N SEQ_FIRST_N

LIST_FIRST_N_D


LIST_FOLD_LEFT SEQ_FOLD_LEFT

LIST_FOLD_LEFT_2ND*


LIST_FOLD_LEFT_2ND_D*


LIST_FOLD_LEFT_d


LIST_FOLD_LEFT_D*



SEQ_FOLD_LEFT_s

LIST_FOLD_RIGHT SEQ_FOLD_RIGHT

LIST_FOLD_RIGHT_2ND*


LIST_FOLD_RIGHT_2ND_D*


LIST_FOLD_RIGHT_d


LIST_FOLD_RIGHT_D*



SEQ_FOLD_RIGHT_s

LIST_FOR_EACH SEQ_FOR_EACH

LIST_FOR_EACH_I SEQ_FOR_EACH_I

LIST_FOR_EACH_I_R SEQ_FOR_EACH_I_R

LIST_FOR_EACH_PRODUCT SEQ_FOR_EACH_PRODUCT

LIST_FOR_EACH_PRODUCT_R SEQ_FOR_EACH_PRODUCT_R

LIST_FOR_EACH_R SEQ_FOR_EACH_R


SEQ_HEAD
ARRAY_INSERT
SEQ_INSERT
ARRAY_INSERT_D



LIST_IS_CONS SEQ_NIL

LIST_IS_NIL


LIST_NIL*

ARRAY_POP_BACK
SEQ_POP_BACK
ARRAY_POP_BACK_Z


ARRAY_POP_FRONT
SEQ_POP_FRONT
ARRAY_POP_FRONT_Z


ARRAY_PUSH_BACK
SEQ_PUSH_BACK
ARRAY_PUSH_FRONT
SEQ_PUSH_FRONT



TUPLE_REM



TUPLE_REM_CTOR
ARRAY_REMOVE
SEQ_REMOVE
ARRAY_REMOVE_D


ARRAY_REPLACE
SEQ_REPLACE
ARRAY_REPLACE_D



LIST_REST


LIST_REST_N SEQ_REST_N

LIST_REST_N_D

ARRAY_REVERSE LIST_REVERSE SEQ_REVERSE TUPLE_REVERSE

LIST_REVERSE_D



SEQ_REVERSE_S
ARRAY_SIZE LIST_SIZE SEQ_SIZE

LIST_SIZE_D



SEQ_SUBSEQ


SEQ_TAIL


SEQ_TO_ARRAY



TUPLE_TO_LIST



TUPLE_TO_SEQ

LIST_TO_TUPLE SEQ_TO_TUPLE

LIST_TO_TUPLE_R


LIST_TRANSFORM SEQ_TRANSFORM

LIST_TRANSFORM_D



SEQ_TRANSFORM_S

おい用意されているマクロ数に差が在りすぎるぞ。一番マクロが多いのがlists、一番少ないのがtuples。その差6倍。

さて、表にまとめてざっと眺めてみるに、次のような特徴が在りそうだ。

arrays
要素の追加削除に強い?
lists
その名の通り、順次処理に強いのだろうか。fold、for each、或いはreverseといった物が目立つ。
sequences
arraysとlistsの両方の特徴を併せ持っているように見える。ただし、それぞれの型で行える処理全てが可能という訳ではなさそうだ。
tuples
なにこれ。

tuplesの存在価値が謎。というかtuplesを操作するマクロの数が少な過ぎて判断が付かない。

各型の変換

表をまとめていて気づいたが、どうも、それぞれの型は相互変換可能という訳ではなさそうだ。図にまとめてみた。

[Boost.Preprocessor各型の変換マクロ一覧]listsとtuples、tuplesとsequencesは相互変換可能。sequencesからarrays、arraysからtuplesの変換は可能だが、その逆は用意されていない。 tuplesとlists、tuplesとsequencesは相互変換が可能。しかし、それ以外の変換は片方向のみ、或いは全く用意されていない。また、arraysに関してはtuplesへの変換しか用意されておらず、名称も他のものとは異なる。

マクロアーギュメント

書籍C++テンプレートメタプログラミングから用語を拝借。

マクロアーギュメントとは、次のものの空でない列である。

  • コンマでも括弧でもない、1つ以上のプリプロセッサトークン、および(または)
  • 左右の括弧に囲まれた、1つ以上のプリプロセッサトークン。
それ以外の変換は片方向のみ、或いは全く用意されていない
例えばlistsとsequencesの変換であれば、tuplesへの変換を経由すれば可能ではある。
ラベル:C++ boost
posted by 天井冴太 at 04:33| Comment(0) | TrackBack(0) | Study | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は180日以上新しい記事の投稿がないブログに表示されております。