如何获取参数中传递的函数名?

时间:2016-02-04 11:35:05

标签: c++ arguments

我刚刚发现了一些东西,因为它获取当前函数的名称或获取调用者的名称,获取一些变体或将名称称为字符串。

我想要的是获取我在参数中传递的函数的名称。像这样:

void Bar()
{
//do something
}

void Foo(void (*f)())
{
//this will output: Foo
std::cout << __FUNCTION__ << std::endl;

//How do I get the name passed to f? (in this case: Bar)
}

int main()
{
Foo(Bar);
return 0;
}

感谢。

编辑:根据@Jose的建议,这是一个非常接近的代码。

    thread_local const char * m_last_function_called = "";
    #define register_function() {m_last_function_called = __FUNCTION__;}
    inline const char * get_last_function() { return m_last_function_called; }

//  const char * g_last_function_called = "";
//  #define register_function() { g_last_function_called = __FUNCTION__; }
//  inline const char * get_last_function() { return g_last_function_called; }

    void print_last_func()
    {
        static std::mutex sync_cout;
        std::lock_guard<std::mutex> l(sync_cout);
        std::cout << get_last_function() << std::endl;
    }

    bool interruptFooTimer = false;
    int FooTimer()
    {
        register_function();
        print_last_func();

        std::cout << "FooTimer.start" << std::endl;
        int t = 0;
        while(t<10)
        {
            if(interruptFooTimer==false)
            {
                sleep(1);
                t++;
                std::cout << "\tt=" << t << std::endl;
            }
            else
            {
                return -1;
            }
        }
        std::cout << "FooTimer.end" << std::endl;
        return 0;
    }

    void CallTrd(int (*f)())
    {
        std::thread TrdTemp(f);
        TrdTemp.detach();
        TrdTemp.~thread();
        print_last_func();
    }

int main()
{
    CallTrd(FooTimer);
    print_last_func();
    int c = 0;
    while(c<15)
    {
        if(c==7) {interruptFooTimer=true;}
        sleep(1);
        c++;
        std::cout << "c=" << c << std::endl;
        print_last_func();
    }
    return 0;
}

观察我在不同时刻调用print_last_func()并获得与变量中初始化值相同的值。此示例代码在不使用join()的情况下调用线程,因为我不能等待线程完成并且还实现了detach()和〜thread来完成我的程序而没有任何异常。我正在使用interruptFooTimer安全地“终止”我的线程。 我错过了什么来获得在register_function中获得的全局值?

4 个答案:

答案 0 :(得分:1)

你做不到。在编译期间,编译器会扩展__FUNCTION__。您无法在运行时获取此信息。

答案 1 :(得分:0)

使用辅助宏:

#define Foo(x) FooHelper(#x, x)
void FooHelper(const char *f_name, void (*f)())
{
    cout << f_name;
}

答案 2 :(得分:0)

我不知道你为什么要这样做,但我希望它能用于调试目的。显然,最简单的方法是将__FUNCTION__作为参数传递出去。但在我看来,这是一个更好的方法。

例如,您可以使用全局变量:

thread_local const char * g_last_function_called = ""; 

#define register_function() { g_last_function_called = __FUNCTION__; }
inline const char * get_last_function() { return g_last_function_called; }

void Bar()
{
    register_function() 
}

void Foo(void (*f)())
{
    std::cout << get_last_function() << std::endl;
}

void my_func_that_doesnt_accept_nulls(CClass * p) 
{
     if (p == nullptr)
     {
        std::cout << " function" << get_last_function();
        std::cout << "passed a bad pointer, fix it" << std::endl;
        return;
     }
}

当然,这不会在多线程中为您提供正确的结果,但您可以使用thread_local const char * g_last_function_called = ""变量来解决这个问题。

我之所以喜欢这种方法,是因为你需要做的就是将它从项目中移除它只是一个简单的&#34;查找和替换&#34; register_function(),因为它使用普通指针,所以根本不能让你的程序变慢。

编辑:这就是我测试代码的方式

void print_last_func()
{
    static std::mutex sync_cout;
    std::lock_guard<std::mutex> l(sync_cout);
    std::cout << get_last_function() << std::endl;
}

void HelloWorld1()
{
    register_function();
    print_last_func();
}

void HelloWorld2()
{
    register_function();
    print_last_func();
}

int main()
{
    register_function();
    std::thread t1(HelloWorld1);
    std::thread t2(HelloWorld2);
    print_last_func();
    t1.join();
    t2.join();
    return 0;
}

我得到:HelloWorld1,HelloWorld2和main

答案 3 :(得分:0)

正如其他人已经指出的那样,你不能直接这样做。

首先,我会使用std::function而不是原始函数指针和std::string来保存函数的名称。

我也会像这样包装它们:

sudo bash
echo "test" > test.html

然后您可以这样使用它:

template<class T>
struct Functor
{
    std::function<T> functor_;
    std::string name_;

    Functor(const std::function<T>& functor, const std::string& name)
        : functor_(functor)
        , name_(name)
    {}
};

您还可以使用宏来简化操作。

void Bar()
{
    // do something
}

void Foo(const Functor<void()>& functor)
{
}

int main() 
{
    Functor<void()> f(std::bind(Bar), "Bar");
    Foo(f);
    return 0;
}

可以这样使用:

#define FUNCTOR(t, x, ...) Functor<t>(std::bind(&x, __VA_ARGS__), #x)

请注意,如果采用此方法,则函数名称可能与使用int main() { auto f = FUNCTOR(void(), Bar); return 0; } 的函数名称不同。