非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++

Non-type pointer and reference template parameters and how/why they are resolved at compile time. c++

本文关键字:为什么 c++ 编译 引用 指针 类型 参数      更新时间:2023-10-16

我简单地问,当我传统上希望在运行时分配和使用内存时,为什么允许通过非类型模板传递对象/基元的内存位置。我知道传递内存的变量必须有外部链接,但鉴于此,这是否意味着外部链接变量的内存位置总是恒定的?举例说明:

template<std::string *temp>
void f();

难道每次执行程序时,通过模板传递的内存位置都会变化,因此不会像我认为的非类型参数所需的模板那样是编译时常数吗?

这类事情由运行时加载程序执行的修复来处理,地址确实会在运行时发生变化,但找到地址的位置始终位于加载的可执行映像的固定位置。

例如,ELF图像格式(目前在*nix上非常常见(具有重新定位部分,该重新定位部分告诉加载器程序中的哪些值需要以某种方式更改。编译器和链接器一起写入足够的信息,链接器能够在运行时生成最终值。

说你有功能:

void Foo::Bar() { }

然后稍后将其作为模板参数传递(非常做作(:

template<typename Class>
struct invoke {
template<void (Class::*Fn)()>
void do_fn(Class * ptr ) { (ptr->*Fn)(); }
};
..
Foo f;
invoke<Foo>::do_fn<&Foo::Bar>(&f);

Foo::Bar和实例化将在可执行映像中的某个特定地址找到,重新定位将告诉实例化的do_fn如何调用实际函数。请注意,do_fn函数名称本身不需要运行时地址,只需要以某种方式计算名称,即所有函数都调用:do_fn<amp;Foo::酒吧>((调用可以解析为单个专门化(每个翻译单元可能都有一个实例化,但链接器必须能够在一个定义规则下丢弃除一个之外的所有实例化,最好是选择哪个实例化无关紧要(。