Michael
Michael

Reputation: 5939

Determining in template function the shortest float type that faithfully represents integer type parameter

template< typename int_type >
bool foo( int_type argument )
{
    float_type value = argument; // float_type must faithfully represent argument.
    ...
}

That is, I'd like to derive within the template function the shortest floating point type float_type that has at least as many significant digits as the template parameter int_type.

foo<int16> should use float.

foo<int32> should use double.

foo<int64> should use long double.

Is this doable without specialization?

Upvotes: 2

Views: 62

Answers (3)

JDługosz
JDługosz

Reputation: 5652

I found that a dummy function signature is the simplest way to map one type to another. Just overload the function with the input types, and those function result types are the output. E.g.

float fff (int16_t);
double fff (int32_t);

using type = decltype(fff(declval<T>()));

Upvotes: 1

fabian
fabian

Reputation: 82461

Indeed this is possible without directly using specializations. You can use std::conditional from the standard header type_traits to define a type conditionally based on the size of int_type:

template< typename int_type >
bool foo(int_type argument)
{
    using float_type = std::conditional<sizeof(int_type) <= 4,
                                        std::conditional<sizeof(int_type) == 4, double, float>::type,
                                        long double>::type;
    float_type value = argument; // float_type must faithfully represent argument.
    ...
}

Upvotes: 2

mattlangford
mattlangford

Reputation: 1260

If you don't mind specialization for looking the value up, you could generate a lookup table to map integer type to floating point type explicitly, like:

template <typename T>
struct IntToFloatHelper;
template <>
struct IntToFloatHelper<int16_t> {
    using type = float;
};
template <>
struct IntToFloatHelper<int32_t> {
    using type = double;
};
template <>
struct IntToFloatHelper<int64_t> {
    using type = long double;
};

// then down in the function...
typename IntToFloatHelper<int_type>::type value = argument;

This works if you're able to enumerate all possible mappings that you want to support. If the type isn't implemented then you'd get a "implicit instantiation of undefined template" error.

After I wrote this I noticed you mentioned "without specialization" so maybe you already were thinking this was a possible way of going about it but were looking for something different.

Upvotes: 0

Related Questions