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

好的,这是另一种方法,包括打印参数名称和类型。它不是很优雅,有两个原因:

  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 回答