Home > Mobile >  C Write Macro for finding an integer type given another integer type
C Write Macro for finding an integer type given another integer type

Time:12-21

I have a function which looks like this:

template<class T, class E, class U = T> T function(T input1, E input2) {
    // implementation here
}

Instead of the above declaration, I want the default for U to be a macro which takes T for input. More specifically, I want the default for U to be boost::multiprecision::cpp_int if T is boost::multiprecision::cpp_int, and I want the default for U to be an integer with double the precision of T for fixed precision T.

I know the second part can be accomplished with:

U = boost::uint_t<2 * std::numeric_limits<T>::digits>::fast

How do I check for T being a cpp_int (or any other arbitrary precision integer within std and boost), and put everything together in a macro?

Edit:

I found that testing for arbitrary precision can be done through:

std::numeric_limits<T>::is_bounded

I still do not know how to combine these 2 tests into 1 macro.

CodePudding user response:

One way could be to use boost::multiprecision::cpp_int if the double size of T is larger than an int64_t.

Idea:

#include <boost/multiprecision/cpp_int.hpp>

#include <cstddef>
#include <type_traits>

// type trait to get an int of the requested size
template<size_t S>
struct int_size {
    using type = std::conditional_t<S==1, int8_t,
                     std::conditional_t<S==2, int16_t,
                         std::conditional_t<S==4, int32_t,
                             std::conditional_t<S==8, int64_t,
                                                boost::multiprecision::cpp_int>>>>;
};

template<size_t S>
using int_size_t = int_size<S>::type;

Then make U double the size of T or boost::multiprecision::cpp_int if it's larger than an int64_t:

template<class T, class E, class U = int_size_t<sizeof(T) * 2>> 
T function(T input1, E input2) {
    // implementation here
}

Demo

CodePudding user response:

Defined a custom boost multiprecision int using a macro, and hid the function backends behind another function which checks types. U is void so that the user has the option of customizing it. If T is fixed precision, the function calls the macro, otherwise passes cpp_int as a template argument. The type deduction of the custom boost int is done at compile time and the if statements are probably evaluated at compile time as well.

#include <limits>
#include <type_traits>

#ifndef BOOST_UINT
#define BOOST_UINT(bit_count) boost::multiprecision::number<boost::multiprecision::cpp_int_backend<bit_count, bit_count, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>
#endif

template<class T, class E, class U = void> T function(T input1, E input2) {
    if(std::is_same<U, void>::value) {
        if(std::numeric_limits<T>::is_bounded) {
            return function_backend<T, E, BOOST_UINT(2 * std::numeric_limits<T>::digits)>(input1, input2);
        } else {
            return function_backend<T, E, cpp_int>(input1, input2);
        }
    } else {
        return function_backend<T, E, U>(input, input2);
    }
}

template<class T, class E, class U> T function_backend(T input1, E input2);
  • Related