提升多精度整数的类型特征
Type trait for boost multiprecision integers
我想编写一个类型特征来识别 boost 多精度整数类型。我可以为 uint256_t
:
这样的具体类型执行此操作
template <typename T>
struct is_multiprecision_int : std::false_type {};
template <>
struct is_multiprecision_int<uint256_t> : std::true_type {};
但是我怎样才能对任何 boost 多精度整数(或至少对具有 cpp_int
后端的任何多精度数字)执行相同的操作?
好的,我来试试看。
根据 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>);
它在我的机器上工作。
请注意,已经存在这样一个特征 - 称为 is_number
并且对于 number<>
class 的任何实例化计算结果为真。还有一个特征 is_number_expression
可以检测从 number<>
.
上的操作派生的表达式模板
我想编写一个类型特征来识别 boost 多精度整数类型。我可以为 uint256_t
:
template <typename T>
struct is_multiprecision_int : std::false_type {};
template <>
struct is_multiprecision_int<uint256_t> : std::true_type {};
但是我怎样才能对任何 boost 多精度整数(或至少对具有 cpp_int
后端的任何多精度数字)执行相同的操作?
好的,我来试试看。
根据 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>);
它在我的机器上工作。
请注意,已经存在这样一个特征 - 称为 is_number
并且对于 number<>
class 的任何实例化计算结果为真。还有一个特征 is_number_expression
可以检测从 number<>
.