2016-11-17 5 views
0

intを返すC API関数をラップしようとしていて、条件をチェックして診断を提供し、エラーが発生した場合に例外をスローするマクロには、マクロ呼び出しにポインタを返すC API関数をラップします

#define CALL_INT(name, ...) do { \ 
     if(!name(__VA_ARGS__)) throw std::runtime_error(#name " failed"); 
    } while(0) 

    // using it 
    CALL_INT(foo, arg); 

が、私はnullptrに対してそのポインタをチェックして、私のポインタに代入する必要があるとして、ポインタを返す関数のは、それほど単純ではありません。私はそれintを必要としないようintを返す関数の場合、それは簡単です。だから、同様のマクロを記述することが可能であるので、この式は動作します:

auto ptr = CALL_PTR(foobar, arg1, arg2); 

それはnullptrに対してfoobar(arg1, arg2)チェック結果を呼び出すコードを生成し、エラーが起こっていない場合は割り当てのために、それが利用可能になるだろう。すなわち。

+0

なぜテンプレートラッパーを作成する代わりに、この方法で作業していますか? – krzaq

+0

@krzaqテンプレートラッパーは関数名を文字列化できません – Slava

+0

マクロのみを使用してテンプレート名付きラッパーに関数名を渡すソリューションは満足いくものでしょうか? – krzaq

答えて

3

本当の解決策は、マクロを使用しないことです。あなたがインラインでしたいと思うように書くだけです。あなたと他の人は、後であなた自身に感謝するでしょう。


リテラルソリューションは、ちょうどすぐにラムダを呼び出すために、次のようになります。

#define MAYBE_THROW(f, ...)         \ 
    [&]{              \ 
     auto _result = f(__VA_ARGS__);      \ 
     if (!_result) throw std::runtime_error(#f " failed"); \ 
     return _result;          \ 
    }() 

MAYBE_THROW(foo, arg); 
auto ptr = MAYBE_THROW(foobar, arg1, arg2); 
+0

インライン関数の問題 - すべての呼び出しで、これがもたらすすべての問題を繰り返して貼り付けコードをコピーする必要があります。 – Slava

+0

作品!ちょうどセミコロンを削除する必要があります。なぜこのラムダで捕まえますか? – Slava

+0

キャプチャする必要があるapi関数にパラメータを渡す@Slava – krzaq

1

少ない魔法はこの式を取る

#define VERIFY(...) \ 
    [&](){ 
    auto r = __VA_ARGS__; 
    if (!r) throw std::runtime_error(#__VA_ARGS__ " failed"); 
    return r; 
    }() 

優れています。それはそれを実行します。それはそれをテストし、失敗した場合にスローします。

失敗した場合、スローに式全体が含まれます。

それを返します。

魔法は少なく、VERIFY(bob)bobとなっています。あなたは

int x = VERIFY(call(a,b,c)); 

または

VERIFY(y = call(a,b,c)); 

または何を行うことができます。プライマリコードが実行されています。失敗した場合には、アサーション・ラッパーのみが欠落しています。

VERIFYは、これを一般的に行うマクロとも呼ばれます。

関連する問題