SlideShare ist ein Scribd-Unternehmen logo
1 von 63
Downloaden Sie, um offline zu lesen
Boost.Preprocessor
   でプログラミングしましょう


                               DigitalGhost
        http://d.hatena.ne.jp/DigitalGhost/
          http://twitter.com/DecimalBloat
私のこと



hatena のプロフィールとか
見てください
とりあえず 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 は省略してます
gcc -P で展開

 1 , 2 , FIZZ , 4 , BUZZ , FIZZ , 7 , 8 ,
FIZZ , BUZZ , 11 , FIZZ , 13 , 14 , FIZZBUZZ
, 16 , 17 , FIZZ , 19 , BUZZ …



    コンパイルすらせず
    解けた!
Boost.Preprocessor について

「コピペ→ちょっとだけ変更」を人間が繰り返す
代わりに、プリプロセッサで自動化するためのマ
クロいろいろ

template<typename T1, typename T2, …,
typename T50> とかいうテンプレート(実際
にBoostにはあります)を作るときとかにとても
便利
使われている例

Boost.ScopeExit
Boost.Typeof
Boost.ConceptCheck
Boost.Parameters
etc...
実行環境

VC : cl.exe /EP ソースファイル
gcc : cpp -P ソースファイル
 ※ cl.exe /EP だと、プリプロセスディレクティブの
 行も空行として残ってしまうので、適当に削除してく
 ださい
 for /f "delims=" %i in ('cl.exe /EP pp.cpp') do @if not "%i"=="" @echo %i
“Hello World!” in Preprocessor

ソース hello.cpp
  Hello, World!



$ gcc -P hello.cpp
  Hello, World!
“Hello World!” in Preprocessor

ソース hello2.cpp
  #define HELLO(x) Hello, x!
  HELLO(x)



$ gcc -P hello2.cpp
  Hello, World!
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, _)
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;
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;
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;
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;
関連するマクロ

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;
関連するマクロ

BOOST_PP_ENUM_SHIFTED_PARAMS(n, d)
  d ## 1, d ## 2, … d ## (n – 1) と展開する

template<
  typename T ## 1 , typename T ## 2 , … typename T ## 50
>
struct vector50;
関連するマクロ

BOOST_PP_ENUM_SHIFTED_PARAMS(n, d)
  d ## 1, d ## 2, … d ## (n – 1) と展開する

template<
  typename T1 , typename T2 , … typename T50
>
struct vector50;
関連するマクロ

関数テンプレートの場合:
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)
);
関連するマクロ

関数テンプレートの場合:
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 ,
);
関連するマクロ

関数テンプレートの場合:
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 ,
);
           ※他にもいくつかバリエーションがあります
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, _)
BOOST_PP_CAT(a, b)

a と b をトークン連結します
a ## b とだいたい同じです
 BOOST_PP_CAT(HOGE, HOGE) // HOGEHOGE
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
                            HOGEDOUBLE(FUGA)
BAD(HOGE, DOUBLE(FUGA))     と展開されてしまう
GOOD(HOGE, DOUBLE(FUGA))
                            (トークン連結のほうが先に

HOGEFUGA FUGA               実行される)

になる
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 がマクロだった場合、全て展開
が終わった後に連結します
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, _)
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」か、もしくはそう展開されるマクロのみ
プリプロセッサでの数字の扱い

プリプロセッサは「1」が示す 値 を認識してい
ない
 「1LL」とか「1.0」は×

 値を認識して扱うのはコンパイルや実行時
プリプロセッサの数字の扱い

「123」や「abc」を「文字の並び(トーク
ン)」として扱っている
丸カッコとカンマ以外の記号や空白が混ざってい
てもトークン
 「123-abc;   .exe」も一つのトークン
関連するマクロ

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)
→
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, _)
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
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, _)
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 では警告がでます)
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, _)
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
もあります
もう一度、数字に関する注意

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
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, _)
FizzBuzz を手動で展開

BOOST_PP_ENUM_SHIFTED(101, FIZZBUZZ_OP, _) を展開

FIZZBUZZ_OP(z, 1, _) ,
FIZZBUZZ_OP(z, 2, _) ,   FIZZBUZZ_OPは、
…                          1→1
FIZZBUZZ_OP(z, 100, _)     2→2
                           3→FIZZ
                           …
                         というようなことをする
FizzBuzz を手動で展開

FIZZBUZZ_OP を C++ で書いてみる
string fizzbuzz_op(int n) {
  string const & fizzbuzz =
      string(!(n % 3) ? "FIZZ" : "")
    + string(!(n % 5) ? "BUZZ" : "");
  return fizzbuzz.empty()
           ? lexical_cast<string>(n)
           : fizzbuzz;
}

(C++的にはすごく効率が悪いですが、後の解説のためな
ので見逃してください)
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)
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 を手動で展開

str1 + str2 → BOOST_PP_CAT(str1, str2)
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;
}
FizzBuzz を手動で展開

c ? "str" : "" → BOOST_PP_EXPR_IIF(c, str)
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;
}
FizzBuzz を手動で展開

!n → BOOST_PP_NOT(n)
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;
}
FizzBuzz を手動で展開

m % n → BOOST_PP_MOD(m, n)
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;
}
FizzBuzz を手動で展開

FIZZBUZZ_OP_II を定義
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 を手動で展開

c ? a : b → BOOST_PP_IIF(c, a, b)
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)
FizzBuzz を手動で展開

str.empty( ) → BOOST_PP_IS_EMPTY(str)
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)
FizzBuzz を手動で展開

fizzbuzz_op をマクロ化
#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 を手動で展開

完成!
#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, _)
もっと複雑な例

make_smart
 newでT型の値を作ってすぐにスマートポインタで管
 理する場合、だいたい
   smart_ptr<T>(new T(param1, param2 …));

 という感じに書く
 これは面倒だし、生のポインタが一瞬登場してしま
 う。完全にポインタを消したい
 関数を作ってラップしてしまおう
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));
}

これでは値で引数を受けているので効率が悪い
参照を使おう
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));
}

これでもまだ const 参照が使えないので不便
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 参照かそうでないかに
よって呼び分けられる
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));
}
make_smart_ptr(n引数版)

3要素タプル版
 1つ目の引数が(略)で、2 * 2 * 2 = 8 パターン

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

結局ここまでだけでも、2 + 4 + 8 + 16 = 30
パターン書かないといけない

           面倒!
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))

BOOST_PP_REPEAT_FROM_TO(1, 6, DEF_MAKE_SMART_OVERLOADS_OP, _)
代入

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

Y は X( ) と展開される
4 と展開したい!
そこで

#define X() 4

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

BOOST_PP_SLOT(1)

BOOST_PP_SLOT(1) は 10 に展開される
素敵!
誰得?

Boost.Typeof は、型を整数の列にエンコード
する必要があるので、型に一意な整数 ID を振る
ために使われています
他に

BOOST_PP_ITERATE
 自分自身を繰り返し #include します
 BOOST_PP_ENUM で書くにはマクロが大きすぎる
 場合に便利
Boost.PP を読むときの注意

BOOST_PP_AUTO_REC というマクロが登場
しますが、これが曲者です
http://d.hatena.ne.jp/DigitalGhost/20090903/1252002035   に概要が
あります
終わり

Weitere ähnliche Inhalte

Was ist angesagt?

わかりやすいパターン認識_2章
わかりやすいパターン認識_2章わかりやすいパターン認識_2章
わかりやすいパターン認識_2章
weda654
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
Akihiko Matuura
 
競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系
tmaehara
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
Takuya Akiba
 
0から理解するニューラルネットアーキテクチャサーチ(NAS)
0から理解するニューラルネットアーキテクチャサーチ(NAS)0から理解するニューラルネットアーキテクチャサーチ(NAS)
0から理解するニューラルネットアーキテクチャサーチ(NAS)
MasanoriSuganuma
 

Was ist angesagt? (20)

わかりやすいパターン認識_2章
わかりやすいパターン認識_2章わかりやすいパターン認識_2章
わかりやすいパターン認識_2章
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
充足可能性問題のいろいろ
充足可能性問題のいろいろ充足可能性問題のいろいろ
充足可能性問題のいろいろ
 
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
 
高速フーリエ変換
高速フーリエ変換高速フーリエ変換
高速フーリエ変換
 
競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系
 
ドロネー三角形分割
ドロネー三角形分割ドロネー三角形分割
ドロネー三角形分割
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界
 
[DL輪読会]Deep Neural Networks as Gaussian Processes
[DL輪読会]Deep Neural Networks as Gaussian Processes[DL輪読会]Deep Neural Networks as Gaussian Processes
[DL輪読会]Deep Neural Networks as Gaussian Processes
 
遺伝的アルゴリズム・遺伝的プログラミング
遺伝的アルゴリズム・遺伝的プログラミング遺伝的アルゴリズム・遺伝的プログラミング
遺伝的アルゴリズム・遺伝的プログラミング
 
双対性
双対性双対性
双対性
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
 
様々な全域木問題
様々な全域木問題様々な全域木問題
様々な全域木問題
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
0から理解するニューラルネットアーキテクチャサーチ(NAS)
0から理解するニューラルネットアーキテクチャサーチ(NAS)0から理解するニューラルネットアーキテクチャサーチ(NAS)
0から理解するニューラルネットアーキテクチャサーチ(NAS)
 
パターン認識と機械学習 §6.2 カーネル関数の構成
パターン認識と機械学習 §6.2 カーネル関数の構成パターン認識と機械学習 §6.2 カーネル関数の構成
パターン認識と機械学習 §6.2 カーネル関数の構成
 
マルコフ連鎖モンテカルロ法入門-1
マルコフ連鎖モンテカルロ法入門-1マルコフ連鎖モンテカルロ法入門-1
マルコフ連鎖モンテカルロ法入門-1
 
競技プログラミング頻出アルゴリズム攻略
競技プログラミング頻出アルゴリズム攻略競技プログラミング頻出アルゴリズム攻略
競技プログラミング頻出アルゴリズム攻略
 
ユークリッド最小全域木
ユークリッド最小全域木ユークリッド最小全域木
ユークリッド最小全域木
 
Feature Selection with R / in JP
Feature Selection with R / in JPFeature Selection with R / in JP
Feature Selection with R / in JP
 

Ähnlich wie Boost.Preprocessorでプログラミングしましょう (6)

Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集
 
プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集
 
Python standard 2022 Spring
Python standard 2022 SpringPython standard 2022 Spring
Python standard 2022 Spring
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 

Mehr von digitalghost

Mehr von digitalghost (8)

ナウなヤングにバカうけのイカしたタグ付き共用体
ナウなヤングにバカうけのイカしたタグ付き共用体ナウなヤングにバカうけのイカしたタグ付き共用体
ナウなヤングにバカうけのイカしたタグ付き共用体
 
拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
 
Define and expansion of cpp macro
Define and expansion of cpp macroDefine and expansion of cpp macro
Define and expansion of cpp macro
 
君はまだ,本当のプリプロセスを知らない
君はまだ,本当のプリプロセスを知らない君はまだ,本当のプリプロセスを知らない
君はまだ,本当のプリプロセスを知らない
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
 
No skk, no life.
No skk, no life.No skk, no life.
No skk, no life.
 
テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式
 
Preprocess-time Lambda Expression
Preprocess-time Lambda ExpressionPreprocess-time Lambda Expression
Preprocess-time Lambda Expression
 

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