编译时可选代码标准题
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。
对于嵌入式系统,我编写了一段代码,它根据编译时间和 运行 时间选择的变量生成延迟。编译时版本归结为编写达到预期 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。