有没有办法在C 17中使这个C 14递归模板更短?

有没有办法在C 17中使这个C 14递归模板更短?,第1张

概述该poly_eval函数将计算在特定x值处评估具有特定系数集的多项式的结果.例如,poly_eval(5,1,-2,-1)计算x ^ 2 – 2x – 1,x = 5.这都是constexpr所以如果给它常量,它将在编译时计算答案. 它目前使用递归模板在编译时构建多项式求值表达式,并依赖于C 14为constexpr.我想知道是否有人能想出一个很好的方法来删除递归模板,可能使用C 17.执行模板的 该poly_eval函数将计算在特定x值处评估具有特定系数集的多项式的结果.例如,poly_eval(5,1,-2,-1)计算x ^ 2 – 2x – 1,x = 5.这都是constexpr所以如果给它常量,它将在编译时计算答案.

它目前使用递归模板在编译时构建多项式求值表达式,并依赖于C 14为constexpr.我想知道是否有人能想出一个很好的方法来删除递归模板,可能使用C 17.执行模板的代码使用clang和gcc中的__uint128_t类型.

#include <type_traits>#include <tuple>template <typename X_t,typename Coeff_1_T>constexpr auto poly_eval_accum(const X_t &x,const Coeff_1_T &c1){    return ::std::pair<X_t,Coeff_1_T>(x,c1);}template <typename X_t,typename Coeff_1_T,typename... Coeff_TList>constexpr auto poly_eval_accum(const X_t &x,const Coeff_1_T &c1,const Coeff_TList &... coeffs){    const auto &tmp_result = poly_eval_accum(x,coeffs...);    auto saved = tmp_result.second + tmp_result.first * c1;    return ::std::pair<X_t,decltype(saved)>(tmp_result.first * x,saved);}template <typename X_t,typename... Coeff_TList>constexpr auto poly_eval(const X_t &x,const Coeff_TList &... coeffs){    static_assert(sizeof...(coeffs) > 0,"Must have at least one coefficIEnt.");    return poly_eval_accum(x,coeffs...).second;}// This is just a test function to exercise the template.__uint128_t multiply_lots(__uint128_t num,__uint128_t n2){    const __uint128_t cf = 5;    return poly_eval(cf,num,n2,10);}// This is just a test function to exercise the template to make sure// it computes the result at compile time.__uint128_t eval_const(){    return poly_eval(5,1);}

另外,我在这里做错了吗?

——–对答案的评论——–

下面有两个很好的答案.一个是clear and terse,but may not handle certain situations involving complex types (expression trees,matrices,etc..) well,虽然它做得很好.它还依赖于有些模糊的运算符.

另一个是不那么简洁,但仍然是much clearer than my original recursive template,and it handles types just as well.它扩展为’cn x *(cn-1 x *(cn-2 …’,而我的递归版本扩展为cn x * cn-1 x * x * cn -2 ….对于大多数合理的类型,它们应该是等价的,并且可以很容易地修改答案以扩展到我的递归扩展到的内容.

我选择了第一个答案,因为它是第一个,它的简洁性更符合我原始问题的精神.但是,如果我要选择一个版本进行制作,我会选择第二个版本.

解决方法 使用逗号运算符的功能(显然是C 17折叠),我想你可以写如下poly_eval()
template <typename X_t,typename C_t,typename ... Cs_t>constexpr auto poly_eval (X_t const & x,C_t a,Cs_t const & ... cs) {   ( (a *= x,a += cs),...,(voID)0 );   return a; }

扔掉poly_eval_accum().

观察第一个系数是否已解释,因此您也可以删除static_assert()并通过复制传递,并成为累加器.

– 编辑 –

添加了一个替代版本来解决返回类型的问题,使用std :: common_type表达式的decltype(),如OP建议的那样;在这个版本中,a再次是一个常量引用.

template <typename X_t,C_t const & c1,Cs_t const & ... cs) {   decltype(((x * c1) + ... + (x * cs))) ret { c1 };   ( (ret *= x,ret += cs),(voID)0 );   return ret; }

– 编辑2 –

额外答案:使用逗号运算符(再次)的功能并初始化未使用的C样式整数数组,也可以避免C14中的递归

template <typename X_t,C_t const & a,Cs_t const & ... cs) {   using unused = int[];   std::common_type_t<decltype(x * a),decltype(x * cs)...>  ret { a };   (voID)unused { 0,(ret *= x,ret += cs)... };   return ret; }
总结

以上是内存溢出为你收集整理的有没有办法在C 17中使这个C 14递归模板更短?全部内容,希望文章能够帮你解决有没有办法在C 17中使这个C 14递归模板更短?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1257270.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存