编译时可选代码标准题

Compile time selectable code standard question

对于嵌入式系统,我编写了一段代码,它根据编译时间和 运行 时间选择的变量生成延迟。编译时版本归结为编写达到预期 CPU 周期计数所需的尽可能多的 NOP 指令。

主要部分是这样的:

#define IS_CONSTEXPR(...) __builtin_constant_p(__VA_ARGS__)
#define FORCE_INLINE      __attribute__((always_inline))

template <int a> struct Nop { 
    __attribute__((always_inline)) static void nop() {
      asm __volatile__("nop");
      Nop<a-1>::nop();
    }
};
template <> struct Nop<0> {
    __attribute__((always_inline)) static void nop() {}
};

void bar(int x) { 
    // TODO: Make an asm version of this to avoid depending on compiler optimization
    for (int i = 0; i < x; i++) 
      Nop<1>::nop(); 
}

template <bool e, int T> struct CTorRT
{   
  FORCE_INLINE CTorRT(int) { 
    if (T == 0) return;
    if (T >= 40) bar(T - 10); // Switch to loop based delay now, since it's above the loop calling overhead 
    else Nop<T>::nop(); // Let's generate a bunch of nop!
  }
};

template <int T> struct CTorRT<false, T>
{
    FORCE_INLINE CTorRT(int v) { bar(v); }
};


#define DELAY_CYCLE(X) { CTorRT<IS_CONSTEXPR(X), IS_CONSTEXPR(X) ? X : 0> a(X); }


int main()
{
   int d = 10;
[...]
   DELAY_CYCLE(30);  // Generates 30 NOP 
   DELAY_CYCLE(d);   // Call bar(10) and loop 10 times over a single NOP loop
[...]
}

该代码在所有编译器(最旧的除外)上的工作方式为 expected

然而,我无法理解为什么它在这部分没有中断:CTorRT< A, A ? X : 0>A 是编译时常量 (constexpr),但 X 可以是动态变量,因此,我的理解是 A ? X : 0 不是 constexpr(即使结果显然是常量表达式所有情况)。

标准的哪一部分暗示表达式:“constexpr_bool ? variable_or_constexpr : constexpr”是一个 constexpr ?

What part of the standard implies that the expression: "constexpr_bool ? variable_or_constexpr : constexpr" is a constexpr ?

没有任何部分,因为 __builtin_constant_p 不是标准函数(或根本不是常规函数),并且三元 而不是 通常是 constexpr.您使用的是编译器扩展的记录行为,而不是标准语言。

GCC docs 专门解决这个问题:

You may also use __builtin_constant_p in initializers for static data. For instance, you can write

static const int table[] = {
    __builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1,
    /* … */
};

This is an acceptable initializer even if EXPRESSION is not a constant expression ...

也就是说,GCC 有效地实现了 ?constexpr 只是为了他们自己的内置。这并不意味着在使用这样的编译器扩展时有 任何 方法来实现相同的事情 except