std :: is_floating_point в некоторых случаях возвращает false для float - PullRequest
0 голосов
/ 12 сентября 2018

В некоторых случаях, см. Один пример ниже, 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 ++?

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

1 Ответ

0 голосов
/ 12 сентября 2018

Ошибка отсутствует, а 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, поскольку контейнеры имеют псевдонимы удобного типа для таких времен.

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

#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

Живая демоверсия

...