What is the best way to determine a common numeric type in a template parameter pack with:
You could use Boost Integer to select the proper cases.
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)));
}