Boost multiprecision : Recursive template instantiation exceeded maximum length 256

元气小坏坏 提交于 2019-12-11 11:34:00

问题


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;
}

with

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;
    }
}

回答1:


Your workaround lacks the understanding.

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.

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.



来源:https://stackoverflow.com/questions/33694512/boost-multiprecision-recursive-template-instantiation-exceeded-maximum-length

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!