【问题标题】:Type trait for boost multiprecision integers提升多精度整数的类型特征
【发布时间】:2020-05-05 21:30:55
【问题描述】:

我想编写一个类型特征来识别提升多精度整数类型。我可以为 uint256_t 之类的具体类型执行此操作:

template <typename T>
struct is_multiprecision_int : std::false_type {};

template <>
struct is_multiprecision_int<uint256_t> : std::true_type {};

但是对于任何提升多精度整数(或至少对于具有cpp_int 后端的任何多精度数字),我该如何做同样的事情?

【问题讨论】:

    标签: c++ boost typetraits boost-multiprecision


    【解决方案1】:

    请注意,已经存在这样的特征 - 称为 is_number 并且对于 number&lt;&gt; 类的任何实例化的计算结果为 true。还有一个特征is_number_expression 可以检测从number&lt;&gt; 上的操作派生的表达式模板。

    【讨论】:

    • 有趣。我猜is_number 可以与numeric_limits&lt;T&gt;::is_integer 结合得到我想要的。
    【解决方案2】:

    好的,我会解决这个问题的。

    根据 boost-multiprecision 的官方文档:https://www.boost.org/doc/libs/1_73_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html,这可能是一个可能的选择:

    #include<type_traits>
    
    using namespace boost::multiprecision;
    
    //helper struct for checking if type is cpp_int_backend at compile time using function overloading
    template<typename T>
    struct is_cpp_int_backend{
        //this template will trigger for pointer to any 
        //  specialisation of cpp_int_backend. Pass by pointer instead
        //  of value, for more generic usage (passing by value will
        //  only work if cpp_int_backend has move constructor defined,
        //  whereas pass-by-pointer will work regardless). References
        //  are also acceptable, however, using pointers will result in
        //  compile error if value is passed, whereas references may give
        //  unexpected behaviour. For these reasons, prefer pointers. 
        template<uint A, uint B, cpp_integer_type CIT, cpp_int_check_type C, typename TT>
        constexpr static std::true_type test(cpp_int_backend<A,B,CIT,C,TT>*);
    
        //this overload has the lowest precedence during overload
        //  resolution, but will accept any argument.  
        constexpr static std::false_type test(...);
    
        //type will be std::true_type or std::false_type depending
        //  on which overload is selected. If T is a specialisation
        //  of cpp_int_backend, it will be true_type, else false_type
        using type = decltype(test(std::declval<T*>())); 
        constexpr static bool value = type::value;
    };
    
    //use similar technique to above, to create type trait for 
    //  multiprecision type
    template<typename T>
    struct is_multiprecision{
    
        //enable this template, if T is a specialisation of 'number'
        //  in boost::multiprecision, and the nested template parameter
        //  is a cpp_int_backend. Use pointers for similar reason as 
        //  above
        template<typename TT, typename = std::enable_if_t<is_cpp_int_backend<TT>::value>>
        constexpr static std::true_type test(number<TT>*);
    
        //again, lowest order of precedence, but will trigger for
        //  anything the above function template does not trigger for
        constexpr static std::false_type test(...);
    
        //get type depending on T
        using type = decltype(test(std::declval<T*>()));
        constexpr static bool value = type::value; 
    };
    
    //variable template for convenience
    template<typename T>
    constexpr bool is_multiprecision_v = is_multiprecision<T>::value;
    
    //example usage
    static_assert(is_multiprecision_v<uint256_t>);
    

    它可以在我的机器上运行。

    【讨论】:

    • 非常感谢!非常有帮助!你能详细说明一下吗?为什么使用指针类型作为 true-test 函数的参数?错误测试中的 (...) 也令人惊讶。
    • @Silicomancer 我的错误,我应该从一开始就包含正确的评论。我已经用相关的 cmets 进行了编辑。如果您需要更多解释,请告诉我。
    • cmets 帮助很大。我对省略号解决方案非常感兴趣。 (...) 是否比 template &lt;typename TT&gt; constexpr static std::false_type test(TT*);constexpr static std::false_type test(auto); 有优势?
    • 是的,constexpr static std::false_type test(...) 具有尽可能低的优先级,并且绝对会接受任何参数。这意味着,如果您调用该函数,如果不存在其他可能的重载,则只有这样才会调用省略号函数。与您的其他建议相比,它更清洁、更简单、更高效且保证有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    相关资源
    最近更新 更多