gpt4 book ai didi

c++ - constexpr 求值分支/constexpr 重载

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:51:02 29 4
gpt4 key购买 nike

设置:

我有一个使用 SIMD 内部函数的函数,我想在一些 constexpr 函数中使用它。

为此,我需要将其设为 constexpr。但是,SIMD 内在函数没有标记为 constexpr,编译器的常量求值器无法处理它们。

我尝试用执行相同操作的 C++ constexpr 实现替换 SIMD 内在函数。该函数在运行时变慢了 3.5 倍,但我能够在编译时使用它(是吗?)。

问题:

如何在常量表达式中使用这个函数而不减慢我的程序在运行时的速度?

一些想法:

  • 为编译器常量表达式求值器添加对所有 SIMD 内在函数的常量求值支持,适用于所有编译器:可能是正确的解决方案,但却是一项不可能完成的艰巨任务。

更务实的解决方案是:

  • 根据函数是否在常量表达式中执行来重载函数(即,提供一个 constexpr 和一个非 constexpr 版本)。
  • 或者,以某种方式在 constexpr 和运行时实现之间的 constexpr 函数内分支(即,在分支中检测该函数是否在常量表达式内执行)。

无论如何,我愿意接受任何能解决我的问题的建议。

提示:

  • @RMartinhoFernandes 在 Lounge 中建议使用 __builtin_constant_p 来检测函数参数是否都是常量表达式,在这种情况下,编译器有望至少尝试在编译时评估函数。

失败的尝试:

  • @Jarod42 提出了直接使用两个独立函数的建议。我想简要地指出为什么这行不通,因为它不是微不足道的。此解决方案假定在调用站点已知函数是否将被 constexpr 评估。但这种情况并非如此。考虑一个调用我的 constexpr 函数,它应该选择我的函数的哪个版本?它必须选择 constexpr 函数才能编译,但“外部”constexpr 函数仍可在运行时求值。在那种情况下,它将使用“慢速”编译时实现,因此,这种方法不能解决问题。

最佳答案

我会这样做

constexpr int doit(int input, bool inconst = false) {
return inconst ? doitconsty(input) : doitfast(input);
}

如果对 doit 的调用是在 constexpr 函数内部,可以在运行时或编译时调用它来执行某些操作,只需转发标志

constexpr int f(int n, bool inconst = false) {
/* ... */
int importantInt = doit(n / 42, inconst);
/* ... */
return magicResult;
}

任何 constexpr 评估都有它开始的地方,如果我没记错的话。在那里传递 inconst

enum foo { bar = f(256, true) }

如果你在运行时世界,就像调用其他任何东西一样调用f

int main() { std::cout << "test-case: " << f(256); }

需要注意的是,这对运算符不起作用,因为你不能在那里添加 bool 参数。相反,您可以以某种不同的方式传递值,如果这适合您(对于像 intbool 这样的原始值,我们也不能重载运算符)。

template<typename T>
struct maybe_const_value {
T t;
bool isconst;
};

enum foo { bar = maybe_const_value{256, true} % magicTransform };

int main() { return maybe_const_value{265} % magicTransform; }

运算符函数然后可以检查 input.isconst 并使用 input.t 作为实际值。

关于c++ - constexpr 求值分支/constexpr 重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42132565/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com