一个检测参数类型,值以及另一个函数的名称和返回值的函数?

时间:2012-10-03 14:16:32

标签: c++ function arguments

我想知道如何编写一个函数来检测参数类型,值和函数名称以及另一个函数的返回值。

例如。我有一个功能:

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

这样的事情。任何建议都非常感谢。谢谢。 尼克

3 个答案:

答案 0 :(得分:2)

一般来说,这是不可能做到的:

  • detector需要在实际返回任何内容之前显示返回值,这与心灵阅读相同
  • 当构建二进制文件时,函数的名称在其中不可用(通常,除了导出)
  • 您的average函数可能根本不是函数,因为编译器可以内联它。

但是,对于特定情况,您可以获得此信息 - 假设您有可用的调试符号,通常不会这样。

答案 1 :(得分: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);

通过更多工作,您还可以打印参数及其值的类型,但其名称(显然,因为名称不是声明的一部分,只是定义的一部分)

答案 2 :(得分:0)

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

  1. 您发送的每个参数都需要一个新的宏,并且......
  2. 这是令人毛骨悚然的宏!我从来没有见过它们优雅地使用过(这也不例外)。
  3. 所以这里是:

    #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
    

    我有点不建议您这样做。但从理论的角度来看,这种方式是可能的。