0

パラメータの型、値、関数名、および別の関数の戻り値を検出する関数をどのように記述できるか疑問に思っています。

例えば。私は機能を持っています:

double average(string datapath, double *data, int numofinput)
{
   // some code here
}

次のように、検出される関数に挿入できる、detector() などの別の関数が必要です。

double average(string datapath, double *data, int numofinput)
{

   // some code here
   detector();
}

検出器は以下を返します。

name: average
returned value: 2.43
pathname: string='C:/Users/Nick/Data/'
data: pointer=0x0065
numofinput: int=17

そのようなもの。どんな提案でも大歓迎です。ありがとう。ニック

4

3 に答える 3

2

一般に、これは実行できません。

  • detector実際に何かを返す前に戻り値を表示する必要があります。これはマインドリーディングと同じです
  • バイナリがビルドされるとき、関数の名前はその内部では利用できません (一般的に、エクスポートを除く)。
  • averageコンパイラがインライン化できるため、関数はまったく関数ではない可能性があります。

ただし、特定のケースでは、この情報を取得できる可能性があります-デバッグシンボルが利用可能であると仮定すると、通常は利用できません。

于 2012-10-03T14:24:51.877 に答える
1

これが(テストされていない)アイデアです:

#define DETECTOR(name, ...) detector_wrapper(name, #name, ##__VA_ARGS__)

template <typename R, typename ...Args, typename ...Brgs>
R detector_wrapper(R(&f)(Args...), char const * name, Brgs &&... brgs)
{
    auto && result = f(std::forward<Brgs>(brgs)...);

    std::cout << "Function name: " << name << std::endl
              << "Return type:   " << demangle(R) << std::endl 
              << "Return value:  " << result << std::endl;

    return result;
}

使用法:

double d = DETECTOR(average, path, data, n);

もう少し作業を行うと、名前ではなく、引数の型とその値を出力することもできます(明らかに、名前は宣言の一部ではなく、定義の一部であるため)。

于 2012-10-03T14:41:27.767 に答える
0

さて、これを行う別の方法があります。これには、パラメーター名とタイプの出力が含まれます。次の2つの理由から、あまりエレガントではありません。

  1. 送信するパラメータの数ごとに新しいマクロが必要です...
  2. それはおかしなマクロです!私はそれらがエレガントに使われているのを見たことがありません(そしてこれも例外ではありません)。

だからここに行きます:

#include <iostream>

#define DETECTOR_0ARG_FUNC(RETTYPE, NAME)   \
            RETTYPE NAME() \
            { \
                std::cout << "Function Name: " #NAME << std::endl; \
                std::cout << "Returns: " #RETTYPE << std::endl; \
                std::cout << "No Parameters" << std::endl;

#define DETECTOR_1ARG_FUNC(RETTYPE, NAME, PARAM1TYPE, PARAM1NAME)   \
            RETTYPE NAME(PARAM1TYPE PARAM1NAME) \
            { \
                std::cout << "Function Name: " #NAME << std::endl; \
                std::cout << "Returns: " #RETTYPE << std::endl; \
                std::cout << "Pameter 1 (" #PARAM1TYPE " " #PARAM1NAME "): " << PARAM1NAME << std::endl;

#define DETECTOR_RETURN(RETTYPE, VALUE) \
                RETTYPE __retval = (VALUE); \
                std::cout << "Returning: " << __retval << std::endl << std::endl; \
                return __retval;

#define DETECTOR_END_FUNC   \
            }


DETECTOR_0ARG_FUNC(int, GetFiveFactorial)

    int result = 1;
    for(int i=5; i>0; i--)
    {
        result = result * i;
    }
    DETECTOR_RETURN(int, result)

DETECTOR_END_FUNC


DETECTOR_1ARG_FUNC(int, GetFactorial, int, initVal)

    int result = 1;
    for(int i=initVal; i > 0; i--)
    {
        result = result * i;
    }
    DETECTOR_RETURN(int, result);

DETECTOR_END_FUNC


int main(int argc, char **argv)
{
    GetFiveFactorial();
    GetFactorial(7);
    return 0;
}

出力:

Function Name: GetFiveFactorial
Returns: int
No Parameters
Returning: 120

Function Name: GetFactorial
Returns: int
Pameter 1 (int initVal): 7
Returning: 5040

私はあなたがこれをすることをちょっとお勧めしません。しかし、理論的な観点からは、この方法で可能です。

于 2012-10-03T15:00:37.330 に答える