获取d中的调用对象或方法

获取d中的调用对象或方法,d,D,有点像 有没有办法从d中的函数或方法中获取调用对象 例如: class Foo { public void bar() { auto ci = whoCalledMe(); // ci should be something that points me to baz.qux, _if_ baz.qux made the call } } class Baz { void qux() { auto foo

有点像

有没有办法从d中的函数或方法中获取调用对象

例如:

class Foo
{
    public void bar()
    {
        auto ci = whoCalledMe();
        // ci should be something that points me to baz.qux, _if_ baz.qux made the call

    }
}

class Baz
{
    void qux()
    {
        auto foo = new Foo();
        foo.bar();
    }
}
问题:

  • whoCalledMe
    这样的东西是否存在?如果是,它叫什么
  • 如果确实存在某个东西,它可以在编译时(在模板中)使用吗?如果是,如何使用
  • 或者

  • 是否可以在运行时访问调用堆栈?就像php的
    debug\u backtrace

  • 无法直接获取有关“来电者”的信息。您可能有幸从调用堆栈中获得地址,但这是一个低级操作,取决于您的程序是否使用堆栈帧编译。在获得地址后,理论上可以将其转换为函数名和行号,前提是程序的二进制文件可以使用调试符号,但(同样)这是高度平台特定的,并且取决于用于编译程序的工具链

    作为替代方案,您可能会发现以下内容很有帮助:

    void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
    {
        writefln("I was called by %s, which is in %s at line %d!", func, file, line);
    }
    
    void caller()
    {
        // Thanks to IFTI, we can call the function as usual.
        callee();
    }
    
    但请注意,您不能对非final类方法使用此技巧,因为对函数的每次调用都将生成一个新的模板实例(并且编译器需要事先知道类的所有虚拟方法的地址)。

    要扩展什么,由于可以使用
    \uuuu function\uuuu
    获取函数的完全限定名,因此也可以使用mixin将函数作为符号获取:

    import std.stdio;
    import std.typetuple;
    
    void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
    {
        alias callerFunc = TypeTuple!(mixin(func))[0];
        static assert(&caller == &callerFunc);
    
        callerFunc();  // will eventually overflow the stack
    }
    
    void caller()
    {
        callee();
    }
    
    void main()
    {
        caller();
    }
    

    堆栈将在此溢出,因为这两个函数最终会无限期地递归调用对方。

    查找调用者是调试器所做的事情,通常需要在编译程序时打开符号调试信息开关。阅读调试信息以了解这一点是高度依赖于系统的,而且非常先进


    异常解除机制也会找到调用者,但这些表不是为不需要它们的函数生成的,并且这些表不包含函数的名称。

    当调用也可以从
    main
    @ratchetfreak进行时,这有点困难:我没有领会你评论的要点?请记住,代码是用来解释一般情况的,而不是用来约束问题的。我认为在任何编译语言中都不可能实现您想要的。关于问题2:在编译时,一个函数可以有多个调用者,你可以得到所有可能调用者的列表(我认为这在D中现在是不可能的)。@MichalMinich:只要我调用的函数是一个模板,我就可以在编译时编译一个函数的专用版本。我发现,甚至使用过,文件和行,但还不知道函数。这些“神奇常数”还有更多吗?
    \uuuuuu函数\uuuuuu
    最近发布。这个关键字家族的列表是。嗯,如果你多次使用它,会增加大量代码膨胀。。。这不是一个理想的解决方案,要避免“代码膨胀”,使模板成为存根,只需将编译时变量作为运行时变量传递给非模板函数。使用
    -inline
    ,就好像第二个函数是用调用站点上指定的文件和行直接调用的一样。通常,
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。否则,每次调用函数时都会再次实例化该函数。通常,将它们作为默认参数添加到函数签名的末尾就可以了。建议任何人使用它们作为模板参数几乎总是不好的建议。另外,当您将它们用作函数参数时,您不需要模板,它可以与虚拟函数一起工作。如果我请求一个功能
    \uuuuu CLASS\uuuuu
    ,就像已经有
    \uuuu FILE\uuuuuuu
    \uuu LINE\uuuuuuuuu
    \uuuuuu函数
    ?当我们这样做的时候,我可能还需要
    \uuuu模块
    。顺便说一句,我非常愿意“做必要的文书工作”。
    \uu模块
    已经实现。您可以从
    \uuuu函数\uuuu
    中提取该类,因为它是完全限定的。@CyberShadow我可以,但为什么需要混乱呢?它似乎太适合其他魔术常数不存在于我。事实上,它的缺失可以被视为有点令人惊讶。必须已经阅读了
    \uuuuu模块
    ,因为它不在代码示例中。我的错。每一种语言的增加都有它的分量。此外,您希望它如何处理嵌套类?