Boost multiprecision:递归模板实例超过最大长度256 [英] Boost multiprecision : Recursive template instantiation exceeded maximum length 256

查看:67
本文介绍了Boost multiprecision:递归模板实例超过最大长度256的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用Boost的多精度数字有点问题,我遇到了以下错误

Trying to play a little bit with boost's multiprecision numbers I got the following error

In file included from main.cpp:1:
In file included from /usr/include/boost/multiprecision/cpp_int.hpp:12:
In file included from /usr/include/boost/multiprecision/number.hpp:16:
In file included from /usr/include/boost/type_traits/is_signed.hpp:15:
In file included from /usr/include/boost/type_traits/is_enum.hpp:14:
In file included from /usr/include/boost/type_traits/intrinsics.hpp:149:
/usr/include/boost/type_traits/is_reference.hpp:32:19: fatal error: recursive template instantiation exceeded maximum
      depth of 256

后面有很多带有实例化错误签名的行.编译以下代码时出现了问题:

followed with lots of lines with the signature of the instantiation error. The problem arised when compiled the following code:

#include<boost/multiprecision/cpp_int.hpp>

using big_int = boost::multiprecision::cpp_int;

big_int getOne(big_int){ return (big_int) 1;}

template<typename T, typename U>
T fastPowMod(T a, U b, T p){
    if(b==0)
        return getOne(a);
    if(b%2 != 0){
        return (a*fastPowMod(a,b-1,p))%p;
    }
    else{
        T aux = fastPowMod(a,b/2,p);
        return (aux*aux)%p;
    }
}

int main(){
    std::cout << fastPowMod<big_int,big_int>(108041234,180611234, 81243) std::endl;
}

使用

clang++ -std=c++11 main.cpp

我不知道为什么会这样,因为用正整数实例化此代码后,该代码可以很好地编译.

I do not know why does this happen, since this code compiles perfectly fine when instantiated with regular integers.

修改:我回答自己.在处理模板和递归时要始终牢记!

Edit: I answer myself. Always remember when dealing with templates and recursion to be explicit!

template<typename T, typename U>
T fastPowMod(T a, U b, T p){
    if(b==0)
        return getOne(a);
    if(b%2 != 0){
        return (a*fastPowMod<T,U>(a,b-1,p))%p;
    }
    else{
        T aux = fastPowMod<T,U>(a,b/2,p);
        return (aux*aux)%p;
    }
}

推荐答案

您的解决方法缺乏了解.

Your workaround lacks the understanding.

问题出在编译器返回延迟评估的表达式模板上.这导致递归调用无限地实例化 fastPowMod 中每个递归级别的不同实例.

The problem comes with the compiler returning lazy-evaluated expression templates. This leads to the recursive calls to instantiate different instantiations for each level of recursion in fastPowMod, infinitely.

您建议的修补程序通过强制递归调用的参数进行求值来禁用它.

Your suggested fix disables it by forcing the arguments to the recursive call to get evaluated.

等效地,您可以完全禁用ET:

Equivalently you might disable ET altogether:

using big_int = bmp::number<bmp::cpp_int::backend_type, bmp::et_off>;

在这种特殊情况下,您可能要考虑将递归转换为迭代,您或编译器可能一次展开一些迭代.这样,您可以保留延迟评估带来的好处.

In this particular case you might want to consider morphing recursion into iteration, which you or the compiler might unroll for some iterations at a time. This way you could retain benefits from the lazy-evaluation.

这篇关于Boost multiprecision:递归模板实例超过最大长度256的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆