2016-07-04 5 views
1

私は、すべての引数(たとえば、最大6)に対して特定の関数を呼び出す可変長マクロを作成したいと考えています。これまでのところ私はMSVCで次のコードを使用してきた:移植性のある可変長マクロ

#define do_write2(x,y) do{do_write(x);do_write(y);}while(0) 
#define do_write3(x,y,z) do{do_write(x);do_write(y);do_write(z);}while(0) 
#define do_write4(x,y,z,w) do{do_write(x);do_write(y);do_write(z);do_write(w);}while(0) 
#define do_write5(x,y,z,w,t) do{do_write(x);do_write(y);do_write(z);do_write(w);do_write(t);}while(0) 
#define do_write6(x,y,z,w,t,u) do{do_write(x);do_write(y);do_write(z);do_write(w);do_write(t);do_write(u);}while(0) 
#define expand(x) x 
#define _get_write(_1,_2,_3,_4,_5,_6,name,...) name 
#define dumpval(...) expand(_get_write(__VA_ARGS__,do_write6,do_write5,do_write4,do_write3,do_write2,do_write))expand((__VA_ARGS__)) 

expandが原因MSVCで__VA_ARGS__の独特の取り扱いに必要とされ、そうでない場合、私は今、私がする必要がある、しかし

error C2660: 'do_write' : function does not take 6 arguments 

を取得しますGCCで同じコードを構築し、そのはそれに問題がある:

error: ‘do_write3’ was not declared in this scope 

は単にexpandラッパーを削除すると、トリックを行います。しかし、#ifdefを使用せずにどちらの場合でもコードをコンパイルするための「正しい」方法はありますか?

+3

これはマクロを使用して*行う必要がありますか? 'C++ 11'を使えますか? –

+0

私はそれを代わりにバリデーショナルテンプレートを使用するよう書き直すことができたと思います。コードはかなり古く、私はこの可能性を考慮しませんでした。 – riv

答えて

1

ここで説明する可変引数マクロのための様々な技術が、あります。ここではVariadic recursive preprocessor macros - is it possible?

はあなたが興味があるかもしれないいくつか実装されている個人的に、私はcall_vla2はあなたがC++ 11のサポートを持っている最高の仮定だと思います。 。これが不可能な場合は、問題の詳細を教えてください。

#include <iostream> 

// target function 
void z(int i) { 
    std::cout << "[" << i << "]\n"; 
} 

// 1. manually specifying the argument count 
#define call1(a)  do{z(a);}while(0) 
#define call2(a,b)  do{z(a);z(b);}while(0) 
#define call3(a,b,c) do{z(a);z(b);z(c);}while(0) 
#define call_n(n, ...) call ## n (__VA_ARGS__) 

// 2. using a variable-length array (GCC compatible) 
// thanks to https://stackoverflow.com/a/824769/6096046 
#define call_vla(...) do { \ 
     int args[] = { __VA_ARGS__ }; \ 
     for(size_t i = 0; i < sizeof(args)/sizeof(*args); i ++) \ 
      z(args[i]); \ 
    } while(0) 

// 3. using a variable-length array and C++11 
#define call_vla2(...) for(auto x : { __VA_ARGS__ }) z(x); 

// 4. using C++11 variadic templates 
template <typename... T> 
void call_n_times() {} 

template <typename... T> 
void call_n_times(int a, T... other) { 
    z(a), call_n_times(other...); 
} 

#define call_template(...) call_n_times(__VA_ARGS__) 

// tests 
int main() { 
    call_n(1, 88);  call_n(3, 1,2,3); 
    call_vla(88);  call_vla(1,2,3); 
    call_vla2(88);  call_vla2(1,2,3); 
    call_template(88); call_template(1,2,3); 
    return 0; 
} 
関連する問題