constexpr求值的分支/constexpr的重载
Branching on constexpr evaluation / overloading on constexpr
设置:
我有一个使用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); }
需要注意的是,这对运算符不起作用,因为您不能在那里添加布尔参数。相反,如果可以的话,您可以用一些不同的方式传递值(对于像int
和bool
这样的基元值,我们也不能重载运算符)。
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
作为实际值。
相关文章:
- 继承函数的重载解析
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 你能重载对象变量名本身返回的内容吗
- 从父命名空间重载类型
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 重载操作程序时出错>>用于类中的字符串 memebr
- 多成员Constexpr结构初始化
- 一个关于在C++中重载布尔运算符的问题
- 不同翻译单元中不可重载的非内联函数定义
- 条件constexpr函数
- 为什么使用SFINAE而不是函数重载
- constexpr 函数中的非文字(通过 std::is_constant_evaluated)
- Visual C++ constexpr Hints
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 将重载的成员函数传递给函数模板
- constexpr 运算符重载使用参数的问题
- 跨编译器的 constexpr 成员函数的重载解析不一致
- constexpr求值的分支/constexpr的重载
- constexpr对于重载很有用