FUNC(param);
でしたら、着払いparam
でchar *
発送致しfunc_string
ます。
の場合int
、発送先func_int
変数の型はコンパイル時に認識されるため、これに対する解決策があると思います..
FUNC(param);
でしたら、着払いparam
でchar *
発送致しfunc_string
ます。
の場合int
、発送先func_int
変数の型はコンパイル時に認識されるため、これに対する解決策があると思います..
これはC1Xでは可能ですが、現在の標準では不可能です。
次のようになります。
#define cbrt(X) _Generic((X), long double: cbrtl, \
default: cbrt, \
float: cbrtf)(X)
変数の型はコンパイラには認識されますが、プリプロセッサには認識されません (コードを単純に非構造化テキストトークンのストリームとして認識し、単純な置換操作のみを実行します)。したがって、C マクロではこれを実現できないと思います。
C++ では、このような問題 (およびそれ以上) を解決するためのテンプレートが発明されました。
タイプの特性をテストできます。
たとえばint
、負の値を保持できますが、保持char*
できません。したがって((typeof(param))-1) < 0
、param
が署名されていない場合:
if (((typeof(param))-1) < 0) {
do_something_with_int();
} else {
do_something_with_char_p();
}
コンパイラは明らかにこれを最適化します。
ここで試してみてください: http://ideone.com/et0v1
タイプのサイズが異なる場合、これはさらに簡単になります。たとえば、さまざまな文字サイズを処理できる汎用マクロを作成する場合は、次のようにします。
if (sizeof(param) == sizeof(char)) {
/* ... */
} else if (sizeof(param) == sizeof(char16_t)) {
/* ... */
} else if (sizeof(param) == sizeof(char32_t)) {
/* ... */
} else {
assert("incompatible type" && 0);
}
GCC には、__builtin_types_compatible_p()
型の互換性をチェックできる組み込み関数があります。
if (__builtin_types_compatible_p(typeof(param), int)) {
func_int(param);
} else if (__builtin_types_compatible_p(typeof(param), char*)) {
func_string(param);
}
ここで試してみてください: http://ideone.com/lEmYE
これをマクロに入れて、やろうとしていることを達成できます。
#define FUNC(param) ({ \
if (__builtin_types_compatible_p(typeof(param), int)) { \
func_int(param); \
} else if (__builtin_types_compatible_p(typeof(param), char*)) { \
func_string(param); \
} \
})
(これ({...})
はGCC のステートメント式であり、ステートメントのグループを右辺値にすることができます。
ビルトインは、__builtin_choose_expr()
コンパイルする式を選択できます。__builtin_types_compatible_p を使用すると、param のタイプが と : の両方int
と互換性がない場合、コンパイル時にエラーをトリガーできますchar*
(この場合、無効なものをコンパイルすることにより)
#define FUNC(param) \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(param), int) \
, func_int(param) \
, __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), char*) \
, func_string(param) \
, /* The void expression results in a compile-time error \
when assigning the result to something. */ \
((void)0) \
) \
)
これは実際には__builtin_choose_expr docsからわずかに変更された例です。
C89 / ANSI C でタイム チェック タイプを実行する可能性はありませんが、それを可能にする gcc の拡張機能があります。私が覚えていれば、typeofまたはそれらの線に沿った何か。Linuxカーネルで一度見ました。
kernel.hで:
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
この記事をご覧ください: Linux カーネルでの GCC ハック
私がこれを最初に見たとき、私は実際にここでSOについて質問しました:
問題を解決するためにどのように使用するのか正確にはわかりませんが、一見の価値があります。
変数の型は確かにコンパイル時に認識されますが、マクロ展開はコンパイル前に行われます。マクロの代わりに 2 つのオーバーロードされた関数を実装することをお勧めします。
これはマクロではできません。マクロの値はコンパイル時に置き換えられ、解釈されません。それらは単なる代替品です。