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

后端 未结 3 565
清酒与你
清酒与你 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:24

    Note: somehow I got it stuck in my head that you needed C++03 for this. This can be simplified for C++11. This also does NOT pick the smallest size.

    There's nothing standard for this to my knowledge, but it can be done: http://coliru.stacked-crooked.com/view?id=c6aa42345f91ab51d745d56573b15a04-4f34a5fd633ef9f45cb08f8e23efae0a

    First the "thinker" structs.

    template struct best_numeric_type 
    {typedef long double type;};
    template<> struct best_numeric_type 
    {typedef long long type;};
    template<> struct best_numeric_type 
    {typedef unsigned long long type;};
    

    Then the base cases:

    template struct best_common_numeric_type1 {
        static const bool isfloat=false;
        static const bool negative=false;
        typedef typename best_numeric_type::type type;
    };
    
    template<> struct best_common_numeric_type1 {
        static const bool isfloat=false;
        static const bool negative=true;
        typedef typename best_numeric_type::type type;
    };//copy-paste for signed char, short, int, long, and long long.
    
    template<> struct best_common_numeric_type1 {
        static const bool isfloat=true;
        static const bool negative=false;
        typedef typename best_numeric_type::type type;
    };//copy-paste for double and long double.
    

    Then the joiners:

    template
    struct best_common_numeric_type2 {
        static const bool isfloat = best_common_numeric_type1::isfloat |  best_common_numeric_type1::isfloat;
        static const bool negative = best_common_numeric_type1::negative |  best_common_numeric_type1::negative;
        typedef typename best_numeric_type::type type;
    };
    template
    struct best_common_numeric_type3 {
        static const bool isfloat = best_common_numeric_type2::isfloat |  best_common_numeric_type1::isfloat;
        static const bool negative = best_common_numeric_type2::negative |  best_common_numeric_type1::negative;
        typedef typename best_numeric_type::type type;
    };
    template
    struct best_common_numeric_type4 {
        static const bool isfloat = best_common_numeric_type3::isfloat |  best_common_numeric_type1::isfloat;
        static const bool negative = best_common_numeric_type3::negative |  best_common_numeric_type1::negative;
        typedef typename best_numeric_type::type type;
    };
    template
    struct best_common_numeric_type5 {
        static const bool isfloat = best_common_numeric_type4::isfloat |  best_common_numeric_type1::isfloat;
        static const bool negative = best_common_numeric_type4::negative |  best_common_numeric_type1::negative;
        typedef typename best_numeric_type::type type;
    };
    

    And finally a test:

    #include 
    #include        
    void printer(long double) {std::cout << "long double\n";}
    void printer(unsigned long long) {std::cout << "ull\n";}
    void printer(long long) {std::cout << "ll\n";}
    void printer(...) {std::cout << "else\n";}
           
    int main() {
        printer(best_common_numeric_type5::type());
        printer(best_common_numeric_type2::type());
        printer(best_common_numeric_type2::type());
        printer(best_common_numeric_type2::type());
        printer(best_common_numeric_type2::type());
        printer(best_common_numeric_type2::type());
    }
    

    Results:

    long double
    ull
    ll
    ll
    ll
    long double
    

提交回复
热议问题