什么是编译时分支?

6

有哪些技术 / c++语言特性可以提供编译时分支?


以下是初步列出的一些(可能会有补充或更正):

  1. Overload resolution : Eg picking the version of the "best" suits the provided arguments

    void F(X& arg);
    void F(X&& arg); 
    
  2. Template specialization : Creating code that runs for "special arguments" - a technique crucial for template metaprogramming and compile time recursion

    template<int N> struct A    { /* implementation */ };
    template<>      struct A<0> { /* specific  code */ };
    
  3. SFINAE & expression sfinae : A special case of (1) that provides the tools for conditional interfaces.

    template<class C, class F>
    auto test(C c, F f) -> decltype((c->*f)(), void()); // 'C' is pointer type
    

1
一个带有编译时表达式的简单 if 语句怎么样? - NPE
4
@NPE:我认为 if 语句不能被视为编译时分支,因为即使 if 有一个常量表达式参数,两个分支都需要被编译。 - Mankarse
1
一般情况下是的,但在优化构建中,死代码可以被消除。 - Neil Kirk
@JamesKanze 它从重载解析中排除函数的方式(特别是在表达式 SFINAE 中)提供了一种看起来像编译时分支的方法论。当然,我发布的所有内容都可以讨论和进一步探索(这是问题的目标)。 - Nikos Athanasiou
1
条件运算符可以在编译时使用:int b[17 >= 12 ? 2 : 4]; - Mankarse
显示剩余6条评论
2个回答

2
你可以使用模板布尔参数来消除运行时分支(在发布版本中,死代码被消除)。
template <bool computeMaxNorm = false>
bool CheckConvergence() {

    if (computeMaxNorm) this->residual_max_norm = 0;

    for (size_t i = 0, I = this->X.Count(); i < I; ++i) {
        double abs_res = abs(this->F_X[i]);
        if (abs_res > this->convergenceCriterion) {
            this->isConverged = false;
            if (!computeMaxNorm) return false;
        }
        if (computeMaxNorm) {
            if (abs_res > this->residual_max_norm) this->residual_max_norm = abs_res;
        }
    }
    return this->isConverged = true;
}

problem.CheckConverge<false>()problem.CheckConverge<true>()更快,而且这个特性不需要运行时间分支。

然而,CPU分支预测通常非常好,编译时的分支可能没有什么区别。


我写了一些非常类似于这个的代码,并检查了输出二进制文件。if语句被删除,生成了两个单独的函数。一个用于true,另一个用于false - XPlatformer
是的,我倾向于滥用这个功能,将多个模板参数与标准参数混合使用。这样可以让您拥有两组默认参数。但这可能是一个不好的做法? - ThreeStarProgrammer57

1
尽管不是严格的编译时分支,您可以添加第四个选项:

4) C++宏

  #if SOMETHING
    ...
  #else
    ...
  #endif

2
这是预处理器时间 - 实际上是文本替换。 - Nikos Athanasiou
2
是的,这就是我说的不是严格的编译时,尽管预处理是编译过程的一部分。 - 101010
编译器会在预处理器之后启动(如果按照您所说的方式,那么链接也是在编译过程中进行的)。 - Nikos Athanasiou
1
@NikosAthanasiou 在你的问题中,你说“编译时”预处理是在编译过程中进行的(即它发生在编译过程中),链接也是在编译过程中进行的。 - 101010
好的,我同意你的观点,预处理器元编程与模板元编程和生成式编程一起被广泛使用,因此尽管我不同意,但我必须承认这是一个需要考虑的工具。 - Nikos Athanasiou
3
严格来说,标准对九个翻译阶段的处理是平等的。尽管只有某些阶段是“编译”,但它们都有可能用于元编程,具有潜在的用途。 - Mankarse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接