Determining the “optimal” common numeric type in a template parameter pack

后端 未结 3 580
清酒与你
清酒与你 2021-01-05 05:02

What is the best way to determine a common numeric type in a template parameter pack with:

  1. the smallest size,
  2. no loss of precision, a
3条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-05 05:25

    You could use Boost Integer to select the proper cases.

    • http://www.boost.org/doc/libs/1_54_0/libs/integer/doc/html/boost_integer/integer.html#boost_integer.integer.sized

    Ignoring for a moment the cases on non-integral element types, here's a quick test of the proposed cases (GCC doesn't have int128_t as it appears):

    Live on Coliru

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace boost;
    
    namespace best_fit_
    {
        // wrappers around Boost Integer http://www.boost.org/doc/libs/1_54_0/libs/integer/doc/html/boost_integer/integer.html#boost_integer.integer.sized
        template  struct select_int;
    
        template  struct select_int {
            using type = typename boost::int_t::least;
        };
    
        template  struct select_int {
            using type = typename boost::uint_t::least;
        };
    
        // query helper
        struct digits {
            template  using apply = mpl::int_::digits>;
        };
    }
    
    template 
    struct best_common_integral
    {
        private:
            using Ints = mpl::vector;
            using Bits = typename mpl::transform::type;
    
            template 
                struct is_signed { static constexpr bool value = std::numeric_limits::is_signed; };
    
            using max  = typename mpl::deref::type>::type;
    
            // sigh, there is no `mpl::any`, AFAICT
            using sign = typename mpl::fold<
                        Ints, 
                        mpl::bool_, 
                        mpl::if_, mpl::bool_, mpl::_1>
                    >::type;
        public:
            using type = typename best_fit_::select_int::type;
    };
    
    #include 
    #include 
    #include 
    
    int main()
    {
        using case1 = best_common_integral;
        using case2 = best_common_integral;
        using case3 = best_common_integral;
        using case4 = best_common_integral;
        using case5 = best_common_integral;
    
        //assert(typeid(case1::type) == typeid(double));
        assert(typeid(case2::type) == typeid(unsigned long));
        assert(typeid(case3::type) == typeid(signed long));
        assert(typeid(case4::type) == typeid(signed long));
        //assert(typeid(case5::type) == typeid(int128_t (maybe)));
    }
    

提交回复
热议问题