• 検索結果がありません。

Boost.Preprocessor でプログラミングしましょう DigitalGhost

N/A
N/A
Protected

Academic year: 2021

シェア "Boost.Preprocessor でプログラミングしましょう DigitalGhost"

Copied!
63
0
0

読み込み中.... (全文を見る)

全文

(1)

Boost.Preprocessor

でプログラミングしましょう

DigitalGhost http://d.hatena.ne.jp/DigitalGhost/ http://twitter.com/DecimalBloat

(2)

私のこと

hatena のプロフィールとか

見てください

(3)

とりあえず FizzBuzz 書いてみた

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

※ include は省略してます

(4)

gcc -P で展開

1 , 2 , FIZZ , 4 , BUZZ , FIZZ , 7 , 8 ,

FIZZ , BUZZ , 11 , FIZZ , 13 , 14 , FIZZBUZZ

, 16 , 17 , FIZZ , 19 , BUZZ …

コンパイルすらせず

解けた!

(5)

Boost.Preprocessor について

「コピペ→ちょっとだけ変更」を人間が繰り返す

代わりに、プリプロセッサで自動化するためのマ

クロいろいろ

template<typename T1, typename T2, …,

typename T50> とかいうテンプレート(実際

にBoostにはあります)を作るときとかにとても

便利

(6)

使われている例

Boost.ScopeExit

Boost.Typeof

Boost.ConceptCheck

Boost.Parameters

etc...

(7)

実行環境

VC : cl.exe /EP ソースファイル

gcc : cpp -P ソースファイル

※ cl.exe /EP だと、プリプロセスディレクティブの

行も空行として残ってしまうので、適当に削除してく

ださい

(8)

“Hello World!” in Preprocessor

ソース hello.cpp

Hello, World!

$ gcc -P hello.cpp

(9)

“Hello World!” in Preprocessor

ソース hello2.cpp

#define HELLO(x) Hello, x!

HELLO(x)

$ gcc -P hello2.cpp

(10)

FizzBuzz はどうなってるの?

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

(11)

BOOST_PP_ENUM_SHIFTED(n, op, data)

展開する数とマクロで、 1 〜 (n 1)

まで数字

を変えながらコピペするマクロ

#define DECLARE_OP(z, n, data) data ## n template<

BOOST_PP_ENUM_SHIFTED(51, DECLARE_OP, typename T) > struct vector50;

(12)

BOOST_PP_ENUM_SHIFTED(n, op, data)

展開する数とマクロで、 1 〜 (n 1)

まで数字

を変えながらコピペするマクロ

#define DECLARE_OP(z, n, data) data ## n template< DECRARE_OP(z, 1, typename T) , DECRARE_OP(z, 2, typename T) , … DECRARE_OP(z, 50, typename T) > struct vector50;

(13)

BOOST_PP_ENUM_SHIFTED(n, op, data)

展開する数とマクロで、 1 〜 (n 1)

まで数字

を変えながらコピペするマクロ

#define DECLARE_OP(z, n, data) data ## n template< typename T ## 1 , typename T ## 2 , … typename T ## 50 > struct vector50;

(14)

BOOST_PP_ENUM_SHIFTED(n, op, data)

展開する数とマクロで、 1 〜 (n 1)

まで数字

を変えながらコピペするマクロ

#define DECLARE_OP(z, n, data) data ## n template< typename T1 , typename T2 , … typename T50 > struct vector50;

(15)

関連するマクロ

BOOST_PP_ENUM_SHIFTED_PARAMS(n, d)

d ## 1, d ## 2, … d ## (n 1)

と展開する

template< BOOST_PP_ENUM_SHIFTED_PARAMS(51, typename T) > struct vector50;

(16)

関連するマクロ

BOOST_PP_ENUM_SHIFTED_PARAMS(n, d)

d ## 1, d ## 2, … d ## (n 1)

と展開する

template<

typename T ## 1 , typename T ## 2 , … typename T ## 50 >

(17)

関連するマクロ

BOOST_PP_ENUM_SHIFTED_PARAMS(n, d)

d ## 1, d ## 2, … d ## (n 1)

と展開する

template<

typename T1 , typename T2 , … typename T50 >

(18)

関連するマクロ

関数テンプレートの場合:

BOOST_PP_SHIFTED_BINARY_PARAMS

template< typename T1 , typename T2 , … typename T50 > tuple50< T1 , T2 , … T50 >

make_tuple50(

BOOST_PP_ENUM_BINARY_PARAMS(50, const T, & arg) );

(19)

関連するマクロ

関数テンプレートの場合:

BOOST_PP_SHIFTED_BINARY_PARAMS

template< typename T1 , typename T2 , … typename T50 > tuple50< T1 , T2 , … T50 >

make_tuple50(

const T ## 1 & arg ## 1 , const T ## 2 & arg ## 2 , …

const T ## 50 & arg ## 50 , );

(20)

関連するマクロ

関数テンプレートの場合:

BOOST_PP_SHIFTED_BINARY_PARAMS

template< typename T1 , typename T2 , … typename T50 > tuple50< T1 , T2 , … T50 >

make_tuple50(

const T1 & arg1 , const T2 & arg2 , …

const T50 & arg50 , );

(21)

FizzBuzz はどうなってるの?

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

(22)

BOOST_PP_CAT(a, b)

a と b をトークン連結します

a ## b とだいたい同じです

(23)

BOOST_PP_CAT(a, b)

それは ## で十分じゃないの?

#define BAD(a, b) a ## b

#define GOOD(a, b) BOOST_PP_CAT(a, b) #define DOUBLE(a) a a BAD(HOGE, DOUBLE(FUGA)) GOOD(HOGE, DOUBLE(FUGA))

HOGEDOUBLE(FUGA)

と展開されてしまう

(トークン連結のほうが先に

実行される)

HOGEFUGA FUGA

になる

(24)

BOOST_PP_CAT(a, b)

ちなみに実装

#define BOOST_PP_CAT(a, b) BOOST_PP_I(a, b) #define BOOST_PP_CAT_I(a, b) a ## b

こうすれば a, b がマクロだった場合、全て展開

が終わった後に連結します

(25)

FizzBuzz はどうなってるの?

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

(26)

BOOST_PP_IIF(cond, t, f)

cond が

「1」というトークンであれば t

「0」というトークンであれば f

BOOST_PP_IIF(1, HOGE, PIYO) → HOGE

BOOST_PP_IIF(0, HOGE, PIYO) → PIYO

※一つめの引数(cond)が受け付けられるのは、「0」

か「1」か、もしくはそう展開されるマクロのみ

(27)

プリプロセッサでの数字の扱い

プリプロセッサは「1」が示す

を認識してい

ない

「1LL」とか「1.0」は

×

(28)

プリプロセッサの数字の扱い

「123」や「abc」を「

文字の並び(トーク

ン)

」として扱っている

丸カッコとカンマ以外の記号や空白が混ざってい

てもトークン

「123-abc; .exe」も

一つの

トークン

(29)

関連するマクロ

BOOST_PP_IF(cond, t, f)

cond が 1〜255 なら t 、0 なら f になる

BOOST_PP_EXPR_IIF(cond, t)

cond が 1 なら t に、 0 なら空トークンになる

BOOST_PP_EXPR_IIF(1, HOGE) → HOGE BOOST_PP_EXPR_IIF(0, HOGE) →

(30)

FizzBuzz はどうなってるの?

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

(31)

BOOST_PP_BOOL(n)

BOOST_PP_NOT(n)

BOOST_PP_BOOL(n)

n が 1〜255 なら 1 、0 なら 0

( n != 0 と同じ)

BOOST_PP_NOT(n)

n が 1〜255 なら 0 、0 なら 1

( !n と同じ) BOOST_PP_BOOL(42) , BOOST_PP_NOT(42) → 1 , 0

(32)

FizzBuzz はどうなってるの?

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

(33)

BOOST_PP_IS_EMPTY(a)

A が空トークンか、空トークンに展開されるな

ら 1 、識別子なら 0

BOOST_IS_EMPTY(HOGE) → 0 BOOST_IS_EMPTY( ) → 1 #define DUMMY BOOST_IS_EMPTY(DUMMY) → 1 (2 番目の例は VC では警告がでます)

(34)

FizzBuzz はどうなってるの?

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

(35)

BOOST_PP_MOD(m, n)

a を b で割った余り(つまり m % n)

BOOST_PP_MOD(5, 3) → 2 BOOST_PP_MOD(BOOST_PP_MOD(139, 25), 8) → 6

BOOST_PP_ADD BOOST_PP_SUB

BOOST_PP_MUL BOOST_PP_DIV

もあります

a を b で割った余り(つまり m % n)

(36)

もう一度、数字に関する注意

BOOST_PP_IIF と同じく、C++ の値を認識し

ているわけではないので、

BOOST_PP_ADD(1 + 1, 2 + 2)

とかはできない

BOOST_PP_ADD(

BOOST_PP_ADD(1, 1),

BOOST_PP_ADD(2, 2))

これはOK

(37)

FizzBuzz はどうなってるの?

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

(38)

FizzBuzz を手動で展開

BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _) を展開 FIZZBUZZ_OP(z, 1, _) , FIZZBUZZ_OP(z, 2, _) , … FIZZBUZZ_OP(z, 100, _)

FIZZBUZZ_OPは、

1→1

2→2

3→FIZZ

というようなことをする

(39)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz =

string(!(n % 3) ? "FIZZ" : "") + string(!(n % 5) ? "BUZZ" : ""); return fizzbuzz.empty() ? lexical_cast<string>(n) : fizzbuzz; }

FIZZBUZZ_OP を C++ で書いてみる

(C++的にはすごく効率が悪いですが、後の解説のためな

ので見逃してください)

(40)

FizzBuzz を手動で展開

この関数をこんな風に置き換え

str1 + str2

BOOST_PP_CAT(str1, str2)

m % n

BOOST_PP_MOD(m, n)

!n

BOOST_PP_NOT(n)

str.empty()

BOOST_PP_IS_EMPTY(str)

c ? "str" : ""

BOOST_PP_EXPR_IIF(c, str)

c ? a : b

BOOST_PP_IIF(c, a, b)

(41)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz =

string(!(n % 3) ? "FIZZ" : "") + string(!(n % 5) ? "BUZZ" : ""); return fizzbuzz.empty() ? lexical_cast<string>(n) : fizzbuzz; }

ここからプリプロセッサで置き換え

(42)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz =

BOOST_PP_CAT(!(n % 3) ? "FIZZ" : "", !(n % 5) ? "BUZZ" : ""); return fizzbuzz.empty() ? lexical_cast<string>(n) : fizzbuzz; }

str1 + str2 → BOOST_PP_CAT(str1, str2)

(43)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz = BOOST_PP_CAT( BOOST_PP_EXPR_IIF(!(n % 3), FIZZ), BOOST_PP_EXPR_IIF(!(n % 5), BUZZ)); return fizzbuzz.empty() ? lexical_cast<string>(n) : fizzbuzz; }

c ? "str" : "" → BOOST_PP_EXPR_IIF(c, str)

(44)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz = BOOST_PP_CAT( BOOST_PP_EXPR_IIF(BOOST_PP_NOT(n % 3), FIZZ), BOOST_PP_EXPR_IIF(BOOST_PP_NOT(n % 5), BUZZ)); return fizzbuzz.empty() ? lexical_cast<string>(n) : fizzbuzz; }

!n → BOOST_PP_NOT(n)

(45)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz = BOOST_PP_CAT( BOOST_PP_EXPR_IIF(BOOST_PP_NOT( BOOST_PP_MOD(n, 3)), FIZZ), BOOST_PP_EXPR_IIF(BOOST_PP_NOT( BOOST_PP_MOD(n, 5)), BUZZ)); return fizzbuzz.empty() ? lexical_cast<string>(n) : fizzbuzz; }

m % n → BOOST_PP_MOD(m, n)

(46)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz =

BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), FIZZBUZZ_OP_II(n, 5, BUZZ)); return fizzbuzz.empty() ? lexical_cast<string>(n) : fizzbuzz; } #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t)

FIZZBUZZ_OP_II を定義

(47)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz =

BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), FIZZBUZZ_OP_II(n, 5, BUZZ)); return BOOST_PP_IIF(fizzbuzz.empty(), n, fizzbuzz); } #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t)

c ? a : b → BOOST_PP_IIF(c, a, b)

(48)

FizzBuzz を手動で展開

string fizzbuzz_op(int n) { string const & fizzbuzz =

BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), FIZZBUZZ_OP_II(n, 5, BUZZ)); return BOOST_PP_IIF(BOOST_PP_IS_EMPTY(fizzbuzz), n, fizzbuzz); } #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t)

str.empty() → BOOST_PP_IS_EMPTY(str)

(49)

FizzBuzz を手動で展開

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t)

fizzbuzz_op をマクロ化

(50)

FizzBuzz を手動で展開

#define FIZZBUZZ_OP(z, n, d) \ FIZZBUZZ_OP_I( \ BOOST_PP_CAT(FIZZBUZZ_OP_II(n, 3, FIZZ), \ FIZZBUZZ_OP_II(n, 5, BUZZ)), \ n) #define FIZZBUZZ_OP_I(t, n) \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY(t), n, t) #define FIZZBUZZ_OP_II(m, n, t) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(BOOST_PP_MOD(m, n)), t) BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _)

完成!

(51)

もっと複雑な例

make_smart

newでT型の値を作ってすぐにスマートポインタで管

理する場合、だいたい

smart_ptr<T>(new T(param1, param2 …));

という感じに書く

これは面倒だし、生のポインタが一瞬登場してしま

う。完全にポインタを消したい

(52)

make_smart_ptr(1引数版)

make_smart(1引数版)

template<typename T, typename T0>

my_smart_ptr<T> make_smart(T0 param0) { return my_smart_ptr<T>(new T(param0)); }

これでは値で引数を受けているので効率が悪い

参照を使おう

(53)

make_smart_ptr(1引数版)

make_smart(1引数版)

template<typename T, typename T0>

my_smart_ptr<T> make_smart(T0 & param0) { return my_smart_ptr<T>(new T(param0)); }

(54)

make_smart_ptr(1引数版)

make_smart(1引数版)

template<typename T, typename T0>

my_smart_ptr<T> make_smart(T0 & param0) { return my_smart_ptr<T>(new T(param0)); }

template<typename T, typename T0>

my_smart_ptr<T> make_smart(T0 const & param0) { return my_smart_ptr<T>(new T(param0));

}

これで、引数が const 参照かそうでないかに

よって呼び分けられる

(55)

make_smart_ptr(2引数版)

1つ目の引数が const / 非 const 、2つ目の引

数が const / 非 const で、2 * 2 = 4 パター

ン必要

template<typename T, typename T0, typename T1>

my_smart_ptr<T> make_smart(T0 & param0, T1 & param1) { return my_smart_ptr<T>(new T(param0, param1));

}

template<typename T, typename T0, typename T1>

my_smart_ptr<T> make_smart(T0 const & param0, T1 & param1) { return my_smart_ptr<T>(new T(param0, param1));

}

template<typename T, typename T0, typename T1>

my_smart_ptr<T> make_smart(T0 & param0, T1 const & param1) { return my_smart_ptr<T>(new T(param0, param1));

}

template<typename T, typename T0, typename T1>

my_smart_ptr<T> make_smart(T0 const & param0, T1 const & param1) { return my_smart_ptr<T>(new T(param0, param1));

(56)

make_smart_ptr(n引数版)

3要素タプル版

1つ目の引数が(略)で、2 * 2 * 2 = 8 パターン

4要素(略)

1つ目(略)で、2 *(略)= 16 パターン

結局ここまでだけでも、2 + 4 + 8 + 16 = 30

パターン書かないといけない

面倒!

(57)

Boost.PP で自動生成

#define DEF_MAKE_SMART_OVERLOADS_OP(z, n, data) \

BOOST_PP_SEQ_FOR_EACH_PRODUCT(DEF_MAKE_TUPLE, ((n)) BOOST_PP_REPEAT(n, MAKE_CONST_SEQ, _)) #define DEF_MAKE_SMART(r, seq) \

DEF_MAKE_SMART_I(BOOST_PP_SEQ_HEAD(seq), BOOST_PP_SEQ_TAIL(seq)) #define DEF_MAKE_SMART_I(n, seq) \

template< typename T , BOOST_PP_ENUM_PARAMS(n, typename T) > \ my_smart_ptr<T> \

make_smart(BOOST_PP_FOR((n, 0, seq), PARAMS_P, PARAMS_OP, DECL_PARAMS)) { \ return my_smart_ptr<T>(new T(BOOST_PP_ENUM_PARAMS(n, param))); \

}

#define PARAMS_P(r, state) PARAMS_P_I state

#define PARAMS_P_I(n, i, seq) BOOST_PP_GREATER(n, i) #define PARAMS_OP(r, state) PARAMS_OP_I state

#define PARAMS_OP_I(n, i, seq) \

(n, BOOST_PP_INC(i), BOOST_PP_SEQ_TAIL(seq)) #define DECL_PARAMS(r, state) DECL_PARAMS_I state #define DECL_PARAMS_I(n, i, seq) \

BOOST_PP_COMMA_IF(i) T ## i BOOST_PP_SEQ_HEAD(seq) & param ## i #define MAKE_CONST_SEQ(z, n, _) (()(const))

(58)

代入

Y は X() と展開される

4 と展開したい!

#define X() 4 #define Y() X() #undef X Y

(59)

そこで

BOOST_PP_SLOT(1) は 10 に展開される

素敵!

#define X() 4 #define BOOST_PP_VALUE 1 + 2 + 3 + X() #include BOOST_PP_ASSIGN_SLOT(1) #undef X BOOST_PP_SLOT(1)

(60)

誰得?

Boost.Typeof は、型を整数の列にエンコード

する必要があるので、型に一意な整数 ID を振る

ために使われています

(61)

他に

BOOST_PP_ITERATE

自分自身を繰り返し #include します

BOOST_PP_ENUM で書くにはマクロが大きすぎる

場合に便利

(62)

Boost.PP を読むときの注意

BOOST_PP_AUTO_REC というマクロが登場

しますが、これが曲者です

http://d.hatena.ne.jp/DigitalGhost/20090903/1252002035

に概要が

(63)

参照

関連したドキュメント

を高値で売り抜けたいというAの思惑に合致するものであり、B社にとって

けいさん たす ひく かける わる せいすう しょうすう ぶんすう ながさ めんせき たいせき

ニホンジカはいつ活動しているのでしょう? 2014 〜 2015

てい おん しょう う こう おん た う たい へい よう がん しき き こう. ほ にゅうるい は ちゅうるい りょうせい るい こんちゅうるい

巣造りから雛が生まれるころの大事な時 期は、深い雪に被われて人が入っていけ

「1 つでも、2 つでも、世界を変えるような 事柄について考えましょう。素晴らしいアイデ

高さについてお伺いしたいのですけれども、4 ページ、5 ページ、6 ページのあたりの記 述ですが、まず 4 ページ、5

○齋藤部会長 ありがとうございました。..