This question has come up before, in particular here Should we generally use float literals for floats instead of the simpler double literals? but I was wondering if there were any better suggested solutions now we are in C++14 land and things like user defined literals and brace initialization exist.
The problem can be expressed as how to write a floating literal in a template function for floating point types
template <typename T> T foo( T x )
{
static_assert( std::is_floating_point<T>::value, "" );
T y = x * 101.0;
return( y );
}
So the question boils down to how do we write "101.0", as it stands it's a double so what happens if I call foo using
float a = 42.0f;
float b = foo( a );
If I write "101.0f" in foo what happens if I call foo with a double, note 101.0 and 101.0f are not necessarily the same.
Also how do I guarantee that no extra code is produced to cast values?
Other suggestions include writing things like "static_cast( 101.0 )", "T( 101.0 )" or other hideous things!
Floating-point literals are numbers that have a decimal point or an exponential part. They can be represented as: Real literals. Binary floating-point literals. Hexadecimal floating-point literals (C only)
Floating-point literals are generally double data type by default. We can assign them to float data types by adding an f at the end of the value.
The simplest form of floating point literal consists of one or more decimal digits and a decimal point ( . ) and an optional suffix ( f , F , d or D ). The optional suffix allows you to specify that the literal is a float ( f or F ) or double ( d or D ) value. The default (when no suffix is specified) is double .
A C++14-specific option would be to use a variable template
namespace detail
{
template<typename F>
F multiplier = F(101.0);
}
template <typename T> T foo( T x )
{
static_assert( std::is_floating_point<T>::value, "" );
T y = x * detail::multiplier<T>;
static_assert(std::is_same<decltype(detail::multiplier<T>), T>{}, "");
return( y );
}
Live demo
template <typename T> T foo( T x ){
static_assert( std::is_floating_point<T>::value, "" );
T y = x * foo_constants<T>::one_o_one;
return( y );
}
Then simply define and specialise your constants in the foo_constants
struct.
You probably don't even need the static assert anymore. You could even extend your function to other algebras (vector products, matrices, quaternions, etc.).
However, it doesn't meet your terseness requirement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With