web-dev-qa-db-ja.com

C ++マクロ「##」は「->」演算子の後に機能しません

次のようにgetメソッドとsetメソッドを持つshared_ptrオブジェクトxがあります。

x->a_value();
x->set_a_value();
x->b_value();
x->set_b_value();

マクロを定義しようとすると:

#define MAC(type) \
  x->set_##type##_value(val);

MAC(a)

それはうまくいきますが、私がそうするとき:

#define MAC(type) \
  x->##type##_value();

MAC(a)

次のコンパイルエラーが発生します:pasting formed '->a', an invalid preprocessing token

23
250

プリプロセッサは「トークン」で動作します-名前と演算子が好きです。

_##_演算子は、小さい部分を貼り付けて新しいトークンを作成します。最初の例では、_set_##type##_value_は_set_a_value_になります。これは有効なトークンです。

2番目の例では、_->##type##_value_は_->a_value_になります。これは、有効なプリプロセッサトークンnotです。それは2つのトークンであるべきです。

x->type##_value();を作成するだけで機能します。個別のトークンx、_->_、_a_value_、_(_、_)_、および_;_を取得します。

51
Bo Persson

錫に書かれていること:->aは、単一の有効なプリプロセッサトークンではありません。2つのトークンです。ここに貼り付ける必要はありません。

#define MAC(type) \
  x->type##_value();
16
Quentin

トークン貼り付け演算子(##)は、2つのトークンを単一の有効トークンに連結するために使用されます。

書くとき

x->##type##_value();
  • 最初に処理されるトークンはxです。

  • 次のトークンは、トークン->typeを連結することにより形成されます。typeaであるため、連結の結果は->a有効なトークンであるべきですが、そうではありません。

したがって、エラーが発生します:pasting formed '->a', an invalid preprocessing token

これを修正するには、単に書く

x->type##_value();

こちらです

  • 解析される最初のトークンはxです。

  • 解析される次のトークンは->です。

  • 次のトークンは、トークンtypeaになります)とトークン_valueを連結して形成されます。これにより、有効なトークンであるa_valueが得られます。

  • 次のトークンは(です。

  • 次のトークンは)です。

  • 最後のトークンは;です。

1
cute_ptr