What is the best way to determine a common numeric type in a template parameter pack with:
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