SlideShare una empresa de Scribd logo
1 de 63
Descargar para leer sin conexión
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   に概要が
あります
終わり

Más contenido relacionado

La actualidad más candente

constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
MITSUNARI Shigeo
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
kikairoya
 

La actualidad más candente (20)

競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
 
C++の黒魔術
C++の黒魔術C++の黒魔術
C++の黒魔術
 
ラムダ計算入門
ラムダ計算入門ラムダ計算入門
ラムダ計算入門
 
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
 
きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうか
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
 
CRC-32
CRC-32CRC-32
CRC-32
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
【Unity道場スペシャル 2017京都】乱数完全マスター 京都編
 
C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)
 
ゲーム木探索技術とコンピュータ将棋への応用
ゲーム木探索技術とコンピュータ将棋への応用ゲーム木探索技術とコンピュータ将棋への応用
ゲーム木探索技術とコンピュータ将棋への応用
 
AVX2時代の正規表現マッチング 〜半群でぐんぐん!〜
AVX2時代の正規表現マッチング 〜半群でぐんぐん!〜AVX2時代の正規表現マッチング 〜半群でぐんぐん!〜
AVX2時代の正規表現マッチング 〜半群でぐんぐん!〜
 
並列化による高速化
並列化による高速化 並列化による高速化
並列化による高速化
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
 

Similar a Boost.Preprocessorでプログラミングしましょう (7)

二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集
 
プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集
 
Python standard 2022 Spring
Python standard 2022 SpringPython standard 2022 Spring
Python standard 2022 Spring
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 

Más de digitalghost

Más de 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
 

Último

Último (11)

論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 

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