Saya punya dua makro FOO2
dan FOO3
:
#define FOO2(x,y) ...
#define FOO3(x,y,z) ...
Saya ingin mendefinisikan makro baru FOO
sebagai berikut:
#define FOO(x,y) FOO2(x,y)
#define FOO(x,y,z) FOO3(x,y,z)
Tetapi ini tidak berhasil karena makro tidak membebani jumlah argumen.
Tanpa memodifikasi FOO2
dan FOO3
, ada beberapa cara untuk mendefinisikan makro FOO
(menggunakan __VA_ARGS__
atau sebaliknya) untuk mendapatkan efek yang sama dari pengiriman FOO(x,y)
untuk FOO2
, dan FOO(x,y,z)
untuk FOO3
?
c
macros
c-preprocessor
Andrew Tomazos
sumber
sumber
Jawaban:
Sederhana seperti:
Jadi, jika Anda memiliki makro ini:
Jika Anda ingin yang keempat:
Tentu, jika Anda mendefinisikan
FOO2
,FOO3
danFOO4
, output akan digantikan oleh makro yang ditentukan.sumber
EXPAND
disebutkan di tautan @ Étienne, Anda pada dasarnya memintanyaGET_MACRO
seperti itu#define FOO(...) EXPAND(GET_MACRO(__VA_ARGS__, FOO3, FOO2, FOO1)(__VA_ARGS__))
dan itu harus diperluas ke jumlah argumen yang tepat di msvc.ISO C++11 requires at least one argument for the "..." in a variadic macro
. Untuk memperbaikinya, tambahkan argumen yang tidak digunakan (atau bahkan hanya koma) setelah param terakhir dalam definisi FOO (...):#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2, UNUSED)(__VA_ARGS__)
( Lihat dijalankan di Coliru ).Untuk menambahkan jawaban netcoder , Anda sebenarnya BISA melakukan ini dengan makro 0-argumen, dengan bantuan
##__VA_ARGS__
ekstensi GCC :sumber
#define FOO0 _Pragma("error FOO0 not allowed")
?FOO0
tidak bekerja di qt + mingw32, panggilanFOO0
akan memanggilFOO1
-std=c99
atau-std=c11
. Anda perlu menggunakan-std=gnu99
atau-std=gnu11
sebagai gantinya_0, ##__VA_ARGS__
dengan_0 __VA_OPT__(,) __VA_ARGS__
adalah cara baru untuk melakukan ini.Ini solusi yang lebih umum:
Tentukan fungsi Anda:
Sekarang Anda dapat menggunakan
FOO
dengan argumen 2, 3 dan 4:Keterbatasan
Ide ide
Gunakan untuk argumen default:
Gunakan untuk fungsi dengan kemungkinan jumlah argumen tak terbatas:
PS:
__NARG__
disalin dari Laurent Deniau & Roland Illig di sini: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1sumber
__NARG_I_
tampaknya sama sekali tidak perlu dan berlebihan. Itu hanya menambah langkah ekstra, dan kebingungan. Saya merekomendasikan menghapus itu sepenuhnya dan hanya mendefinisikan__NARG__
sebagai gantinya sebagai:#define __NARG__(...) __ARG_N(__VA_ARGS__,__RSEQ_N())
._VFUNC_
: hapus saja. Kemudian, definisikan_VFUNC
sebagai:#define _VFUNC(name, n) name##n
bukan#define _VFUNC(name, n) _VFUNC_(name, n)
.Saya sendiri sedang meneliti ini, dan saya menemukan ini di sini . Penulis menambahkan dukungan argumen default untuk fungsi C melalui makro.
Saya akan mencoba meringkas artikel secara singkat. Pada dasarnya, Anda perlu mendefinisikan makro yang dapat menghitung argumen. Makro ini akan menghasilkan 2, 1, 0, atau rentang argumen apa pun yang dapat didukungnya. Misalnya:
Dengan ini, Anda perlu membuat makro lain yang mengambil sejumlah variabel argumen, menghitung argumen, dan memanggil makro yang sesuai. Saya telah mengambil contoh makro Anda dan menggabungkannya dengan contoh artikel. Saya memiliki fungsi panggilan FOO1 a () dan fungsi panggilan FOO2 dengan argumen b (jelas, saya mengasumsikan C ++ di sini, tetapi Anda dapat mengubah makro untuk apa pun).
Jadi kalau sudah
Preprocessor memperluas itu ke
Saya pasti akan membaca artikel yang saya tautkan. Ini sangat informatif dan ia menyebutkan bahwa NARG2 tidak akan bekerja pada argumen kosong. Dia mengikuti ini di sini .
sumber
Ini adalah versi yang lebih ringkas dari jawaban di atas . Dengan contoh.
Lari:
Perhatikan bahwa memiliki keduanya
_OVR
dan_OVR_EXPAND
mungkin terlihat berlebihan, tetapi perlu bagi preprosesor untuk memperluas_COUNT_ARGS(__VA_ARGS__)
bagian, yang jika tidak diperlakukan sebagai string.sumber
Mungkin Anda bisa menggunakan makro ini untuk menghitung jumlah argumen .
sumber
Ini adalah spin off dari jawaban Evgeni Sergeev. Yang ini mendukung kelebihan argumen nol !
Saya menguji ini dengan GCC dan MinGW. Seharusnya bekerja dengan versi lama dan baru dari C ++. Perhatikan bahwa saya tidak akan memberikan jaminan untuk MSVC ... Tetapi dengan beberapa penyesuaian, saya yakin itu dapat dibuat untuk bekerja dengan itu juga.
Saya juga memformat ini untuk ditempelkan ke file header (yang saya sebut macroutil.h). Jika Anda melakukannya, Anda bisa memasukkan header ini apa pun yang Anda butuhkan fitur, dan tidak melihat nastiness yang terlibat dalam implementasi.
sumber
Ini tampaknya berfungsi dengan baik pada GCC, Dentang dan MSVC. Ini adalah versi yang sudah dibersihkan dari beberapa jawaban di sini
sumber
#define func0() foo
? Sayangnya, versi saat ini tidak menangani kasus ini.