web-dev-qa-db-ja.com

std :: is_floating_pointは、floatに対してfalseを返す場合があります

場合によっては、以下の1つの例を参照してください。_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などの他のライブラリで試すこともできます。

15
Clèm

バグはなく、std::is_floating_pointが正しい答えを示しています。

vector<float>[n]floatを提供しません。 それはあなたにfloat& を与えます。

typeidはこれを無視します 便宜上ですが、より「強力な」ツールとして、decltypestd::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

ライブデモ