Типаж для целых чисел повышенной точности - PullRequest
2 голосов
/ 06 мая 2020

Я хочу написать свойство типа для идентификации целочисленных типов с повышенной точностью. Я могу сделать это для конкретного типа, такого как uint256_t:

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

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

Но как я могу сделать то же самое для ЛЮБОГО целого числа повышенной точности (или, по крайней мере, для любого числа многопоточности с бэкендом cpp_int)?

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Обратите внимание, что такая черта уже существует - называется is_number и принимает значение true для любого экземпляра класса number<>. Существует также признак is_number_expression, который обнаруживает шаблоны выражений, полученные в результате операций с number<>.

1 голос
/ 06 мая 2020

Хорошо, я займусь этим.

На основании официальной документации по 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>);

Работает на моей машине.

...