它目前使用递归模板在编译时构建多项式求值表达式,并依赖于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递归模板更短?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)