std :: is_floating_point возвращает false для float в некоторых случаях

В некоторых случаях, см. Один пример ниже, std::is_floating_point возвращает false для 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;
}

Выход из GCC

f
not floating point

В этом примере можно видеть, что typeid рассматривает ::std::vector< float >()[::std::vector< float >().size()] как float поскольку возвращает правильное имя. Также можно проверить, что typeid(decltype(::std::vector< float >()[::std::vector< float >().size()])) == typeid(flat) возвращает true. Однако std::is_floating_point возвращает false. Зачем? Это ошибка от C++?

FYI, я проверил как с GCC, так и с VisualStudio. В этом примере я использовал std :: vector, но можно также попробовать другие библиотеки, такие как Eigen.

Ответ 1

Нет ошибки, и std::is_floating_point дает вам правильный ответ.

vector<float>[n] не дает вам float; он дает вам float&.

typeid игнорирует это для удобства, но, поскольку более "мощные" инструменты, decltype и std::is_floating_point нет.

Вы можете использовать std::remove_reference чтобы исправить это:

if (::std::is_floating_point_v<std::remove_reference_t<
   decltype(::std::vector< float >()[::std::vector< float >().size()])
>>)

Вы также можете рассмотреть std::decay.

decltype любом случае вам не нужен decltype поскольку контейнеры имеют удобные псевдонимы типов в такие моменты.

Вот что я сделал бы:

#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

Демо-версия