简体   繁体   English

模板实际上必须是编译时构造吗?

[英]Do templates actually have to be compile-time constructs?

Does the C++ Standard actually mandate that templates must be instantiated at compile-time, not run-time? C++ 标准是否真的要求模板必须在编译时而不是运行时实例化?

If not, is it a convention that we use purely because it obviously makes sense to do it that way?如果不是,我们使用它是否纯粹是因为这样做显然是有意义的? Or is there some practical reason that would, theoretically, prevent an implementation from existing that can instantiate templates at run-time?或者是否有一些实际的原因会从理论上阻止可以在运行时实例化模板的实现?

All the standard requires is that the observable behavior be as if the templates were instantiated before the program started to run.所有标准要求的是可观察行为就像在程序开始运行之前实例化模板一样。 Any errors, for example, would have to trigger a message in some phase of the compilation, or at least before runtime.例如,任何错误都必须在编译的某个阶段或至少在运行之前触发一条消息。 In theory, a compiler could probably defer full instantiation until runtime, but in practice, it would have to have done most of the work at compile time anyway, in order to be sure that any potential error messages appeared.理论上,编译器可能会将完整实例化推迟到运行时,但实际上,无论如何它都必须在编译时完成大部分工作,以确保出现任何潜在的错误消息。

In a stricter sense, the standard considers "translation" as a unit;严格意义上,该标准以“翻译”为单位; an implementation could, and implementations have (and I think some still do) defer instantiation until link time.一个实现可以,并且实现已经(我认为有些仍然这样做)将实例化推迟到链接时间。 Which leads to interesting questions when dynamic linking is involved.当涉及动态链接时,这会导致有趣的问题。 But the standard is silent about that: dynamic linking is really undefined behavior, as far as the standard is concerned, so it is up to the implementation.但是标准对此保持沉默:就标准而言,动态链接实际上是未定义的行为,因此取决于实现。

In the end, however: instantiating templates is one of the most expensive operations a compiler does, and requires a very large and complex mechanism.然而,最终:实例化模板是编译器所做的最昂贵的操作之一,并且需要非常庞大和复杂的机制。 Which no vendor wants to impose on an executable.没有供应商想强加给可执行文件。 So regardless of the loopholes, don't expect to see run time instantiation any time soon.所以不管有什么漏洞,不要指望很快就会看到运行时实例化。 Especially as it wouldn't buy you anything anyway: the standard requires that all templates can be instantiated at compile time, so you couldn't instantiate a template somehow dependent on a runtime argument and still be standard conform.特别是因为它无论如何都不会给你买任何东西:标准要求所有模板都可以在编译时实例化,所以你不能以某种方式实例化依赖于运行时参数的模板并且仍然符合标准。

You can't create types in a C++ program at run time (while it is running);您不能在运行时(运行时)在 C++ 程序中创建类型; they are all known at compile time.它们在编译时都是已知的。 Even dynamically loaded shared libraries don't change that;即使是动态加载的共享库也不会改变这一点; the set of types in the library is known at compile time (when the library is compiled), and the loading program must be able to handle the types that the library exposes.库中的类型集在编译时(编译库时)是已知的,加载程序必须能够处理库公开的类型。

So, there is no need for template evaluation at run time;因此,在运行时不需要进行模板评估; the information is all known at compile time.这些信息在编译时都是已知的。

If you were to instantiate templates at run time, you'd need the compiler and the linker services as part of the run time.如果要在运行时实例化模板,则需要编译器和链接器服务作为运行时的一部分。 That greatly complicates the required run time environment - to no obvious advantage.这极大地使所需的运行时环境复杂化 - 没有明显的优势。

Clearly, an interpretive C++ system could, probably would, defer the template instantiation until needed - JIT (just in time) processing.显然,解释性 C++ 系统可能会推迟模板实例化,直到需要 - JIT(及时)处理。 But the compilation is still done before the code is executed.但是编译仍然是在代码执行之前完成的。

I'm not in the habit of reading the standard, but Stroustrup's C++ Programming Language is usefully precise.我没有阅读标准的习惯,但 Stroustrup 的 C++ 编程语言非常精确。

A.9 Templates: gives the grammar for template declaration; A.9 Templates:给出模板声明的语法; the type-parameter is one of class, typename, or another template - so the type is known, static. type-parameter 是 class、typename 或另一个模板之一 - 所以类型是已知的,静态的。 (it's not dynamic. one could imagine giving a typeinfo object if C++ were a dynamic language. But that wasn't your question.) (它不是动态的。如果 C++ 是一种动态语言,人们可以想象给出一个 typeinfo 对象。但这不是你的问题。)

C.13.8.3 Point of Instantiation Binding: says that the point of instantiation for a template is just before the declaration using it. C.13.8.3 实例化点绑定:表示模板的实例化点就在使用它的声明之前。

The example given is concerned with resolving names in the template definition to the correct scope.给出的示例涉及将模板定义中的名称解析为正确的范围。 This would be very hard to do at run-time!这在运行时很难做到!

eg from Stroustrup C.13.8.3:例如来自 Stroustrup C.13.8.3:

template<class T> void f(T a) { g(a); }

void g(int);

void h()
{
    extern g(double);
    f(2);
}

"Here the point of instantiation for f is just before h(), so the g() called in f() is the global g(int) rather than the local g(double)." “这里 f 的实例化点就在 h() 之前,所以在 f() 中调用的 g() 是全局 g(int) 而不是局部 g(double)。”

I guess this doesn't rule out JIT, but as a practical matter, instantiating the template f requires knowing the correct scoped resolution of g at a particular line.我想这并不排除 JIT,但实际上,实例化模板 f 需要知道特定行处 g 的正确范围分辨率。 As Jonathan says, you'd need the compiler's services as part of the run-time, along with the full context built up in the compiler while compiling that unit.正如乔纳森所说,您需要编译器的服务作为运行时的一部分,以及在编译该单元时在编译器中构建的完整上下文。 If that's not a "compile-time" job, I don't know what is.如果这不是“编译时”工作,我不知道是什么。

EDIT: This all relies on an antique version of the C++ standard.编辑:这一切都依赖于 C++ 标准的古董版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM