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

Kri*_*ris 5 d

我之前的问题有点相关

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

例:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 有类似whoCalledMe存在吗?如果是这样,它叫什么?
  2. 如果确实存在,可以在编译时使用(在模板中),如果存在,如何使用?

另外;

  1. 是否可以在运行时访问调用堆栈?喜欢用php debug_backtrace

And*_*vić 5

要扩展Cyber​​Shadow所说的内容,因为您可以通过使用__FUNCTION__获得函数的完全限定名称,您还可以使用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();
}
Run Code Online (Sandbox Code Playgroud)

堆栈将在这里溢出,因为这两个函数最终无限地递归地相互调用.


Vla*_*eev 4

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

作为替代方案,您可能会发现这很有帮助:

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();
}
Run Code Online (Sandbox Code Playgroud)

但请注意,不能对非最终类方法使用此技巧,因为每次调用该函数都会生成一个新的模板实例(并且编译器需要事先知道类的所有虚拟方法的地址)。

  • 最近[添加](https://github.com/D-Programming-Language/dmd/pull/1462)`__FUNCTION__`。该关键字系列的列表位于[此处](http://dlang.org/traits.html#specialkeywords)。 (2认同)
  • 一般来说,`__FILE__`、`__LINE__`和`__FUNCTION__`只能用作函数参数,而不是模板参数。否则,每次调用该函数时都会再次实例化该函数。通常,将它们作为默认参数添加到函数签名的末尾就可以了。建议任何人使用它们作为模板参数几乎总是坏建议。此外,当您将它们用作函数参数时,您不需要模板,并且它将与虚函数一起使用。 (2认同)