【问题标题】:Is there an analogue of an object's `this`, but for functions?是否存在对象的“this”的类似物,但对于函数?
【发布时间】:2014-01-26 18:54:59
【问题描述】:

我已经搜索了参考资料和一般网络,但我无法找到它是否存在。

有没有办法在 C++ 中获取指向当前函数的指针?它是如此微不足道,它应该存在。

在完美的世界中,我想找到一种方法来获取当前函数的std::function,但即使是旧式指针也可以。

澄清为什么需要它:我正在考虑 Lambda 函数内部的递归,甚至是函数中的一般递归,在未来版本中更改名称的可能性很大。

【问题讨论】:

  • 你可以使用函数名作为它的指针。和这个无关
  • 一个函数没有实例化,所以没有this。您仍然可以使用指向您的函数的普通指针(即使在模板化函数中也应该可以)
  • 我不得不说,虽然这个概念不是必需的,但我仍然喜欢这个想法。例如,递归函数不必知道自己的名称。如果你重命名它,你不必触摸函数的主体。
  • @KarolyHorvath 实际上我在考虑递归。但我会没有它。
  • @KarolyHorvath:相关:stackoverflow.com/q/21143835/560648

标签: c++ this function-pointers


【解决方案1】:

没有,主要是因为没有必要。在(非匿名函数)函数的上下文中,您始终知道自己所处的位置——您始终可以使用它的名称来引用它或获取它的地址。与对象不同,不同的对象有不同的地址,因此需要this

【讨论】:

  • @Cheersandhth.-Alf 所以 Lambda 内部没有递归?
  • @Cheersandhth.-Alf 我不确定我是否理解你关于模板实例化的观点,你能扩展一下吗?
  • @LuchianGrigore:您可以使用提供的模板参数的名称(假设没有重载,我猜),但不能单独使用名称。
  • 啊,好吧,我知道,以为你的意思是别的。
【解决方案2】:

一般来说你不能。例如,在可转换为原始函数指针的 lambda 中,没有(标准语言)方法可以在函数内部获取该指针。

但是,您可以通过宏 __func__ 以原始字符串的形式获取 函数名称,但只有最新版本的编译器会为其提供该宏名称。

此外,如果您对不可移植代码感到满意,那么还有一些特定于编译器的自省工具(我只知道它们存在,但您必须在谷歌上搜索它们才能列出它们)。


解决问题的新增部分,如何让函数递归并仍然支持简单的名称更改和/或 lambdas。

一种方法是使用std::function,但更简单(并且可能更高效)是将递归函数定义为内部实现细节,例如在命名空间或内部类中:

#include <iostream>
using namespace std;

void foo( int const x )
{
    struct Recursive {
        inline static void foo( int const x )
        {
            cout << x << ' ';
            if( x > 0 ) { foo( x - 1 ); }
        }
    };

    Recursive::foo( x );
    cout << endl;
}

auto main() -> int
{
    foo( 3 );
}

如何使用 lambda 而不是命名函数来完成上述操作:

#include <iostream>
using namespace std;

auto main() -> int
{
    auto const foo = []( int const x ) -> void
    {
        struct Recursive {
            inline static void foo( int const x )
            {
                cout << x << ' ';
                if( x > 0 ) { foo( x - 1 ); }
            }
        };

        Recursive::foo( x );
        cout << endl;
    };

    foo( 3 );
}

【讨论】:

  • 出于兴趣,为什么是auto main() -&gt; intvoid foo( int const x )?只是踢轮胎,还是不同风格有一些巧妙的暗示?
  • @SteveJessop:有巧妙的暗示。 :) 一个有表达式结果,另一个没有。因此它们在某些语言中有所不同,例如帕斯卡functionprocedure
  • 酷,谢谢。因此,如果您编写的函数模板返回 decltype(或其他依赖类型),根据模板参数可能是也可能不是 void,那么约定就会失效? ;-) 也就是说,可能会使用函数样式定义一些杂项过程,否则您一眼就能看出区别。
  • @SteveJessop;在特殊情况下重新“崩溃”,是的,但如果你这样做,那么它就会散发出设计错误的味道。 ;-) 根本不。这也是为什么某些语言在语法上区分它们的原因,以及为什么 C 语言将它们混为一谈通常被称为“非常糟糕的语言设计错误”的原因。
【解决方案3】:

如果目的只是为了获取一个std::function对象,你可以使用函数名本身:

#include <iostream>
#include <functional>
using namespace std;

void functionA(int a);

void functionA(int a)
{
    cout << "Thanks for calling me with " << a << endl;

    if(a == 22)
        return;

    std::function<void(int)> f_display = functionA;

    f_display(22);
}

int main() {

    functionA(1);

    return 0;
}

http://ideone.com/4C9gc5

但不幸的是,这并不能幸免于名称更改。您也可以将函数封装到其他东西中以摆脱名称更改:

#include <iostream>
#include <functional>
using namespace std;

void functionA(int a)
{
    cout << "Thanks for calling me with " << a << endl;
}

template <typename F>
void encapsulateFunction(F f, int val)
{
    std::function<void(int)> f_display = f;

    // f_display now points to the function encapsulated
    f_display(val);
}



int main() {

    encapsulateFunction(functionA, 22);

    return 0;
}

http://ideone.com/5Xb0ML

【讨论】:

    【解决方案4】:

    你可以这样做:

    std::map<string, boost::any> functions;
    int foo(int x) {
       int (*fp)(int) = boost::any_cast<int (*)(int)>(functions[__func__]); 
       return x;
    }
    
    int main(int argc, char* argv[])
    {
        int (*fooPointer)(int) = foo;
        boost::any fp = fooPointer;
        functions["foo"] = fp;
        ...
    }
    

    将对该函数的引用插入到全局映射中并从函数中检索它。仍然有封装地图的空间,但我希望这个想法是明确的。

    在 c++ 中,函数不是一等公民,因此您必须做一些工作才能获得函数的引用。

    【讨论】:

    • 如果你想获得一个函数的引用,那么你需要使用一个函数指针并为其赋值。你能用其他方式吗?
    • 重读问题:“有没有办法在 C++ 中获取指向 current 函数的指针?”
    • 当然,现在您必须通过参数或全局变量将该引用传递给函数。我会用宏包装它。
    • 我是来学习的,但我仍然没有看到任何其他方法。并不是说我曾经需要这样的东西。
    • 至少完成您的示例代码 - “将该引用传递给函数”。现在答案不完整
    猜你喜欢
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    相关资源
    最近更新 更多