【问题标题】:What is compile time function in C++?什么是 C++ 中的编译时函数?
【发布时间】:2020-05-19 10:30:45
【问题描述】:

我在这里搜索了这个问题(关于 SO),据我所知,所有问题都假设什么是编译时函数,但初学者几乎不可能知道这意味着什么,因为要知道的资源是相当罕见。

我找到了简短的wikipedia article,它展示了如何通过在 C++ 中编写以前从未见过的枚举使用来编写难以理解的代码,还有一个 video,它是关于它的未来,但对此几乎没有解释。

在我看来,用 C++ 编写编译时函数有两种方法

  1. constexpr
  2. template<>

我已经对它们进行了简短的介绍,但我不知道它们是如何出现在这里的。

谁能用一个足够好的例子来解释编译时函数,使它包含它最相关的特性?

【问题讨论】:

  • 我建议你把问题的范围缩小一些,因为现在它就像一个问题中的 5-10 个问题。您可以随时创建新的
  • 对我来说似乎足够好
  • 编译时函数是一个函数,它将由编译器编译时执行。我认为这就是这么简单。所以consteval 函数是一个编译时函数。 constexpr 函数可以在编译时执行,如果在核心常量表达式中调用它。模板不是编译时函数。它们是在编译时生成的,但不是在编译时执行的(至少,不能保证)。您可以使用模板在编译时计算事物,但它们不是函数。
  • 我现在想到的是:源代码 => 目标代码 => 机器代码 => 运行。把它放在哪里?
  • @AjayMishra 这是一种简化的图片。例如,预处理器首先运行,模板有点像预处理器——模板本身被实例化,创建新的(隐藏的)源代码,然后编译成目标代码。顺便说一句,目标代码是机器代码。也许,您可以编写可执行的二进制文件,而不是机器代码。

标签: c++ templates constexpr compile-time


【解决方案1】:

正如您所提到的,在 cpp 中,有两种方法可以在编译时评估代码 - constexpr 函数和 template 元编程。

这些解决方案之间存在一些差异。 template 选项较旧,因此受到更广泛的编译器的支持。另外templates 保证在编译时被评估,而constexpr 有点像内联——它只建议编译器可以在编译时进行工作。对于templates,参数通常通过模板参数列表传递,而constexpr 函数将参数作为常规函数(它们实际上是)。 constexpr 函数更好,因为它们可以在运行时作为常规函数调用。

现在的相似之处 - 必须可以在编译时评估它们的参数。因此它们必须是文字或其他编译时函数的结果。

说了这么多,让我们看看编译时间max函数:

template<int a, int b>
struct max_template {
    static constexpr int value = a > b ? a : b;
};

constexpr int max_fun(int a, int b) {
    return a > b ? a : b;
}

int main() {
    int x = 2;
    int y = 3;
    int foo = max_fun(3, 2); // can be evaluated at compile time
    int bar = max_template<3, 2>::value; // is surely evaluated at compile time
//  won't compile without compile-time arguments  
//  int bar2 = max_template<x, y>::value; // is surely evaluated at compile time
    int foo = max_fun(x, y); // will be evaluated at runtime
    return 0;
}

【讨论】:

  • constexpr 函数具有可见的定义,允许在运行时上下文中从编译器进行优化。 constexpr 是一个很好的提示,就像inline 在优化中更加“积极”。它在编译时的评估并不比该上下文中的常规函数​​更多。
  • 你演示了一个类模板,而不是一个函数模板——它可以像普通函数一样被调用。
【解决方案2】:

正如您所看到的,“编译时函数”不是 C++ 构造,它只是在编译时计算东西(因此是函数)的想法(而不是在运行时计算或通过单独的构建编译器之外的工具)。 C++ 以多种方式实现了这一点,您发现了其中两种:

  • 模板确实可以用来计算任意东西,这是一组称为“模板元编程”的技术。这主要是偶然的,因为它们根本不是为此目的而设计的,因此疯狂的语法和与旧编译器的斗争。但在 C++03 及之前的版本中,这就是我们所拥有的一切。

  • constexpr 在看到编译时计算的需求后已添加到 C++11 中,并将它们带回到更理智的领域。从那以后,它的工具带一直在扩展,只需在正确的位置添加constexpr,就可以在编译时运行越来越多看起来很正常的代码。

还可以提到宏元编程,其中 Boost.Preprocessor 就是一个很好的例子。但它比老式的模板元编程更加古怪和令人憎恶,所以如果你有选择的话,你可能不想使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 2021-08-11
    • 1970-01-01
    相关资源
    最近更新 更多