LoginSignup
8
5

More than 3 years have passed since last update.

boost.diのannotations `BOOST_DI_INJECT(Hoge , (named = int1) int a, double b)` みたいな文法ってどういう原理なの?

Last updated at Posted at 2019-12-05

※boost.diそのものに関する話は出てきません。ご了承ください
この記事は 2019C++アドベントカレンダー (https://qiita.com/advent-calendar/2019/cpp) 5日目の記事になります

boost.diのannotations

boost.diには(今気にすべきことだけを言うと)「オブジェクトの構築を補助する機能」が含まれている
その中にはannotationsというものがあり、以下のようにコンストラクタ引数に名前を付ける機能がある

// 名前用型
auto int1 = [] {};
// 型定義
struct Hoge {
  BOOST_DI_INJECT(Hoge , (named = int1) int a, double b) // aに"int1"という名前を付ける
     : a(a), b(b) {}
  int a = 0;
  double b = 0;
};
auto injector = di::make_injector(
    di::bind<int>().named(int1).to(42)  //intでint1という名前のパラメタを42で初期化
    , di::bind<double>().to(3.14)  // doubleのパラメタを3.14で初期化
);
auto x = injector.create<Hoge>(); // 便利に構築。何が便利なのかはboost.diのドキュメントかDIに関する記事を読んでくれ 

// 想定通りにオブジェクトが構築された
std::cout<<x.a<<std::endl;  // 42
std::cout<<x.b<<std::endl;  // 3.14

しかし、BOOST_DI_INJECT(Hoge , (named = int1) int a, double b)(named = int1) int aという文法はC++的に考えて奇妙だ。しかもこのannotations、付けてもつけなくてもよい
これはどういったトリックだろうか?

大雑把な実装原理

#define B(_) A
#define TEST(X) B X

上のようなマクロを書いたとき、TEST(X)X

  • (hoge) 1 の場合: B(_)で置換されてtoken列 A 1 になる
  • 1の場合: それ以上置換できるルールが存在しないのでtoken列 B 1になる

ことを利用している

もう少し具体的な挙動

#define PP_CAT(L,R) PP_CAT2(L,R)
#define PP_CAT2(L,R) L##R
#define AA 1,
#define AB 0,
#define B(_) A
#define TEST(X) PP_CAT(A,B X)
  • TEST((1)1)
    • TEST((1)1) -> PP_CAT(A,B(1)1) -> PP_CAT2(A,A 1) -> AA 1 -> 1,1 のように置換される
  • TEST(1)
    • TEST(1) -> PP_CAT(A,B 1) -> PP_CAT2(A,B 1) -> AB 1 -> 0,1 のように置換される

このように置換すれば最終的にいい感じのtoken列に変換できるので、あとはマクロなりで好きな個所を取り出しいい感じに使える using type = なんとか でもなんでも生やしてほしい

boost.diにおける実装

https://github.com/boost-experimental/di/blob/v1.1.0/include/boost/di/aux_/preprocessor.hpp#L102
この行のあたりの挙動を追ってほしい

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5