Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 678
Clèm Avatar asked Sep 12 '18 09:09

Clèm


1 Answers

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

like image 144
Lightness Races in Orbit Avatar answered Nov 05 '22 16:11

Lightness Races in Orbit