3

次のようなマクロを記述する方法はありますか。

#define G(x1, x2, ... , xn) f(x1), f(x2), ... , f(xn)

それとも、個人ごとにこれを定義する必要がありますnか?

C++0x の回答は問題ありません。

編集:一般的に可変数の引数をとるマクロではなく、この形式のマクロを作成する方法を尋ねています。

目標: : だから私は次のようなことをすることができます:

#define MAKE_TUPLE(x1, x2, ... , xn) mytuple<decltype((x1)), decltype((x2)), ... , decltype((xn))>{x1, x2, ... , xn}

したがって、これmytupleは、移動やコピーを行わずに作成することも、集約構築を使用してその場で作成できた可能性のある一時ファイルへの不要な参照を作成することもできません。

4

3 に答える 3

5

目標:[再び間違ったアプローチの説明を削除]。したがって、このmytupleは、移動やコピーなしで作成できます。また、集約構造を使用してその場で作成できた可能性のある一時的なものへの不要な参照もありません。

コメントで要件をより正確にしました

私のパラメータパックを渡すことは、理想的には、通常の引数の受け渡しとできるだけ速くする必要があります。これらのパラメータパックはかなり大きくなる可能性があると思います。

あなたは完全に間違った道を進んできました。以下はマクロではなく、移動やコピーを作成せず(マクロ以下)、一時的なものへの不要な参照はありません(要件の最後の部分が何を意味するかはわかりませんが、繰り返し明確にすることができると思います)。それは他に何もしていないので、「通常の引数の受け渡し」と同じくらい高速です。

template<typename ...T>
mytuple<T...> make_tuple(T&&... t) {
  return mytuple<T...>{std::forward<T>(t)...};
}

decltypeこれは、引数のタイプに関して、指定する一連の式とは異なる動作をしますX

  • Prvaluesは次のようにタプルに転送されますX
  • X値は次のようにタプルに転送されますX
  • 左辺値は次のようにタプルに転送されますX&

マクロの動作が異なります

  • Prvaluesは次のようにタプルに転送されますX
  • X値は次のようにタプルに転送されますX&&
  • 左辺値は次のようにタプルに転送されますX&

真ん中の部分に注意してください。タプルの存続期間が常にすべての引数の存続期間より短い場合を除いて、参照がぶら下がる傾向がありますが、prvaluesをとして保存するXと不要なコピーが作成されます。次のように、常に参照を使用するmytuple<T&&...>ために私のコードで使用します

  • Prvaluesは次のようにタプルに転送されますX&&
  • X値は次のようにタプルに転送されますX&&
  • 左辺値は次のようにタプルに転送されますX&
于 2011-06-09T23:03:55.847 に答える
5

少しぎこちない構文を使用する場合は、Boost.Preprocessor のシーケンスを使用できます。

#include <boost/preprocessor.hpp>

#define G(args) BOOST_PP_SEQ_FOR_EACH_I(G_GENF, x, args)
#define G_GENF(r, data, i, elem) \
    BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i, 0)) f(elem)

使用法:

G((a))
G((b)(c))
G((d)(e)(f))

結果:

f(a)
f(b) , f(c)
f(d) , f(e) , f(f)

構文が必要な場合G(a, b, c)は、マクロ置換は再帰的ではないため、渡す引数の数ごとに 1 つのマクロが必要になると思います。ただし、ソースの他の場所で使用されている単一のマクロからこれらのマクロに委任することはできます。検討:

// Utility for counting the number of args in the __VA_ARGS__ pack:
#define PP_NARGS(...) PP_NARGS2(__VA_ARGS__, PP_NARGS_COUNT())
#define PP_NARGS2(...) PP_NARGS_IMPL(__VA_ARGS__)
#define PP_NARGS_IMPL(x1, x2, x3, N, ...) N
#define PP_NARGS_COUNT() 3, 2, 1, 0, ERROR

// Macros to delegate to concrete, defined-arity implementations:
#define XF(count, ...) XF_IMPL (count, __VA_ARGS__)
#define XF_IMPL(count, ...) XF_ ## count (__VA_ARGS__)

// Defined-arity implementations:
#define XF_1(x1)         f(x1)
#define XF_2(x1, x2)     f(x1), f(x2)
#define XF_3(x1, x2, x3) f(x1), f(x2), f(x3)

// Delegation macro; this is the only macro you need to call from elsewhere:
#define G(...) XF(PP_NARGS(__VA_ARGS__), __VA_ARGS__)    

使用法:

G(a)
G(b, c)
G(d, e, f)

結果:

f(a)
f(b), f(c)
f(d), f(e), f(f)

これは確かにさらに一般化することができ、一部のプリプロセッサ ユーティリティ ライブラリには、これを行う機能が既にある場合がありますが、これはどのように行うことができるかを示しています。(私は C99/C++0x プリプロセッサ ライブラリに詳しくないので、お勧めできません。)

于 2011-06-09T03:01:03.813 に答える
0

思い出すと、Boost Preprocessorライブラリは C++98 でもこれを行うことができます。

ただし、マクロは悪であり、避けるのが最善です。

代わりに次のようなことを考えてください

Type const values[] = {x1, x2, x3, ... xn};

for( int i = 0;  i < countOf( values );  ++i )
{
    f( values[i] );
}

乾杯 & hth。

于 2011-06-09T03:17:11.310 に答える