2012-11-08 5 views
11

インスタンス化される関数の戻り値の型をパラメータとして取得するテンプレートを作成したいと思います。"現在の関数"の戻り値の型を取得する方法はありません

例えば、私はResultテンプレートクラスをしましたと仮定します。

template<type T> 
class Result { 
    T _result_value; 
    T& operator=(T that); 
    ~Result(); 
} 

このクラスにはいくつかの専門分野があるでしょう。デストラクタでは戻り値の型をログに記録したいと思います。operator=割り当て内でエラー値を確認してアサートしたいと思います。

理想的には、私が持ってできるようにしたいと思い、このような定義:

#define RESULT Result< /* decltype magic for type of current function */ > 

はので、私はそれを使用することができます: Result<HFILE>に推測されます

HFILE MyOpenFile(...) { 
    RESULT result; 
} 

...。これは単純な例です。Result<HFILE>の代わりにRESULTを書くことは大したことではありませんが、現在の関数の戻り値の型が簡単に得られないシナリオがあります。

+0

あなたはhttp://en.wikipedia.org/wiki/Decltypeを使用することができますか? – bobah

+1

少なくとも、関数名をマクロに渡す必要があります(例えば、 'RESULT(MyOpenFile)')、オーバーロードの場合でも、あいまいさに遭遇します。 [現在の関数へのポインタを取得しています](http://stackoverflow.com/q/2154852/1468366)でも、やり直しが難しく、正しい型付きのポインタを取得することは、関数の名前を変更しなければ不可能に見えます。 – MvG

+0

@MvGを使用すると、 'decltype'に関数+ paramsを渡すことでオーバーロードのあいまいさを回避できます。 'decltype(foo(b))'、 'decltype(foo(a、b))'は正しく解決されます。しかし、それは痛みです。 – Nim

答えて

4

いいえ「現在の関数」を参照するC++には何もありません。一番近いのは__func__ですが、文字列リテラルです。したがって、decltypeには何も渡されません。

autoとは必要ありません。

3

タイプを推論するために参照できるメモリ内に専用のオブジェクトがないため、関数内からはできません。クラスは可能です。decltype(*this)

3

私はdecltypeを使用していると考えることができる最もポータブルな方法:

#define RESULT(func, ...) Result<decltype(func(__VA_ARGS__))> 

int main(int argc, char **argv) { 
    RESULT(main, argc, argv) result; // same as `Result<int> result;` 
} 

しかし、これは、関数名とそれがRESULTマクロにかかるすべての引数を渡すことを強制します。現在の関数への識別子や渡された引数を取得するための移植性がない(そしてコンパイラ固有のものでもない)ため、これは避けられないと私は考えています。引数はオーバーロードのあいまいさのために問題を通過しました。ここで

はSSCCEです:http://ideone.com/cPTjjF

+2

varargsビジネスは必要ありません。単純に 'RESULT'を' RESULT(f)Result 'と定義し、' RESULT(main(argc、argv)) 'として使用してください。 – Nim

関連する問題