std::is_floating_point returns false for float in some cases
In some cases, see one example below, std::is_floating_point is returning false for float.
#include <iostream>
#include <type_traits>
#include <vector>
int main()
{
::std::cout << typeid(decltype(::std::vector< float >()[::std::vector< float >().size()])).name() << ::std::endl;
if (::std::is_floating_point< decltype(::std::vector< float >()[::std::vector< float >().size()]) >::value)
{
::std::cout << "floating point" << ::std::endl;
}
else
{
::std::cout << "not floating point" << ::std::endl;
}
return 0;
}
Output from GCC
f
not floating point
In this example, one can see that typeid considers ::std::vector< float >()[::std::vector< float >().size()] as a float as it returns the correct name. One can also check that typeid(decltype(::std::vector< float >()[::std::vector< float >().size()])) == typeid(flat) returns true. However, std::is_floating_point is returning false. Why? Is that a bug from C++?
FYI, I checked with both GCC and VisualStudio. In this example, I used std::vector, but one can also try with other libraries, such as Eigen.
There is no bug, and std::is_floating_point is giving you the right answer.
vector<float>[n] doesn't give you a float; it gives you a float&.
typeid ignores this for convenience but, as more "powerful" tools, decltype and std::is_floating_point do not.
You can use std::remove_reference to fix this:
if (::std::is_floating_point_v<std::remove_reference_t<
decltype(::std::vector< float >()[::std::vector< float >().size()])
>>)
You might also consider std::decay.
You don't need decltype anyway as containers have handy type aliases for times like this.
Here's what I'd do:
#include <iostream>
#include <type_traits>
#include <vector>
int main()
{
using V = std::vector<float>;
::std::cout << typeid(V::value_type).name() << '\n';
if (::std::is_floating_point_v<V::value_type>)
::std::cout << "floating point\n";
else
::std::cout << "not floating point\n";
}
// Output:
// f
// floating point
Live demo
#include <iostream>
#include <type_traits>
#include <vector>
int main()
{
::std::cout << typeid(decltype(::std::vector< float >()[::std::vector< float >().size()])).name() << ::std::endl;
if (::std::is_floating_point< decltype(::std::vector< float >()[::std::vector< float >().size()]) >::value)
{
::std::cout << "floating point" << ::std::endl;
}
else
{
::std::cout << "not floating point" << ::std::endl;
}
return 0;
}
Output from GCC
f
not floating point
In this example, one can see that typeid considers ::std::vector< float >()[::std::vector< float >().size()] as a float as it returns the correct name. One can also check that typeid(decltype(::std::vector< float >()[::std::vector< float >().size()])) == typeid(flat) returns true. However, std::is_floating_point is returning false. Why? Is that a bug from C++?
FYI, I checked with both GCC and VisualStudio. In this example, I used std::vector, but one can also try with other libraries, such as Eigen.
There is no bug, and std::is_floating_point is giving you the right answer.
vector<float>[n] doesn't give you a float; it gives you a float&.
typeid ignores this for convenience but, as more "powerful" tools, decltype and std::is_floating_point do not.
You can use std::remove_reference to fix this:
if (::std::is_floating_point_v<std::remove_reference_t<
decltype(::std::vector< float >()[::std::vector< float >().size()])
>>)
You might also consider std::decay.
You don't need decltype anyway as containers have handy type aliases for times like this.
Here's what I'd do:
#include <iostream>
#include <type_traits>
#include <vector>
int main()
{
using V = std::vector<float>;
::std::cout << typeid(V::value_type).name() << '\n';
if (::std::is_floating_point_v<V::value_type>)
::std::cout << "floating point\n";
else
::std::cout << "not floating point\n";
}
// Output:
// f
// floating point
Live demo
Comments
Post a Comment