[There are a few questions on this but none of the answers are particularly definitive and several are out of date with the current C++ standard].
My research shows these are the principal methods used to check if a floating point value can be converted to an integral type T
.
if (f >= std::numeric_limits<T>::min() && f <= std::numeric_limits<T>::max() && f == (T)f))
using std::fmod
to extract the remainder and test equality to 0.
using std::remainder
and test equality to 0.
The first test assumes that a cast from f
to a T
instance is defined. Not true for std::int64_t
to float
, for example.
With C++11, which one is best? Is there a better way?
Use std::fmod(f, 1.0) == 0.0
where f
is either a float
, double
, or long double
. If you're worried about spurious effects of unwanted floating point promotions when using float
s, then use either 1.0f
or the more comprehensive
std::fmod(f, static_cast<decltype(f)>(1.0)) == 0.0
which will force, obviously at compile time, the correct overload to be called. The return value of std::fmod(f, ...)
will be in the range [0, 1) and it's perfectly safe to compare to 0.0
to complete your integer check.
If it turns out that f
is an integer, then make sure it's within the permitted range of your chosen type before attempting a cast: else you risk invoking undefined behaviour. I see that you're already familiar with std::numeric_limits
which can help you here.
My reservations against using std::remainder
are possibly (i) my being a Luddite and (ii) it not being available in some compilers partially implementing the C++11 standard, such as MSVC12. I don't like solutions involving casts since the notation hides that reasonably expensive operation and you need to check in advance for safety. If you must adopt your first choice, at least replace the C-style cast with static_cast<T>(f)
;