1

我有一个 D 模块,我希望它包含公共和私人部分。我尝试在函数定义之前使用关键字 private 和 static。我有一个函数,我希望将其设为可外部调用/公开,理想情况下我希望它在调用站点内联。该函数调用其他模块内部函数,这些函数旨在为私有的,即不可外部调用。对这些的调用成功地内联在模块中,并且许多垃圾被 CTFE 和已知常量传播处理掉了。然而,GDC 编译器也会生成这些内部例程的副本,即使它们已在需要的地方内联并且它们不应该是外部可调用的。我正在使用 -O3 -frelease 进行编译。我应该做什么 - 即使我使用静态和/或私有,我应该期待吗?

我还简要查看了有关 GCC 的这个线程,希望获得洞察力。

正如我之前提到的,我已经尝试在这些内部函数上同时使用私有和静态,但我似乎无法抑制代码生成。如果调试器需要拥有这些例程的副本来设置断点,我可以理解这一点。我需要强调的是,据我所知,这可能会在链接时以某种方式解决。我没有尝试链接程序,我只是在使用 GDC 查看 Matt Godbolt D Compiler Explorer 中生成的代码。一切都可以用零长度的模板参数列表制作成模板(例如 auto my_fn()( in arg_t x ) ),尝试过,它没有帮助但没有害处。

其他几件事要尝试:我可以尝试使用私有部分创建一个静态类,作为实现包的一种方式,Ada 风格。(严格要求是单实例。)我从来没有做过任何 C++,只有专业的大量 asm 和 C。所以这将是一个学习曲线。

我能想到的唯一另一件事是使用嵌套函数定义,Pascal/Ada 风格,将内部例程移动到调用者的主体内。但这有很多缺点。

粗略的例子

module junk;

auto my_public_fn() {  return my_private_fn();  }

private
static // 'static' and/or 'private', tried both
auto my_private_fn() { xxx ; return whatever; }
4

1 回答 1

2

我刚刚与 Iain 就此进行了简短的讨论,实现它并不像看起来那么简单。

首先static在D中有很多含义,但是翻译单元本地函数的C含义不是其中之一;-)

因此,将这些功能标记为private似乎很直观。毕竟,如果你不能从翻译单元外部访问一个函数,而且你永远不会向函数泄露地址,为什么不删除它呢?在这种情况下,它可能完全未使用或内联到所有调用者中。

现在有一个问题:我们不能确定一个函数是否未被使用:

private void fooPrivate() {}

/*template*/ void fooPublic()()
{
    fooPrivate();
}

编译文件时,GDC 对模板一无所知fooPublic(因为模板只有在实例化时才能被完全分析),因此fooPrivate似乎没有使用。当稍后fooPublic在不同的文件中使用时,GDC 将依赖于fooPrivate已经在原始源中发出 - 毕竟它不是模板,因此它不会被发出到新模块中。

可能有解决方法,但整个问题似乎并不简单。我们还可以为此引入一个自定义gcc.attribute属性。它会导致与模板相同的问题,但由于它是一个用例的特定注释(与 不同private),我们可以依靠用户来做正确的事情。

于 2017-03-02T19:41:37.187 回答