Domanda

So you can make a fake is_integral in C++98 with the following:

template <typename T>
struct is_integral
{
  static const bool value;
};

template <typename T>
const bool is_integral<T>::value = std::numeric_limits<T>::is_integer;

easy enough...is there anything similar you can do for floating point (without getting a boost dependency?)

È stato utile?

Soluzione

The C++ standard* states:

Specializations shall be provided for each fundamental type, both floating point and integer, including bool.

(*- I am having trouble finding an earlier draft of the standard. If someone can lend a hand here, it'd be much appreciated.)

Since std::numeric_limits provides definitions for is_integer and is_specialized, you can combine the information to deduce whether or not a type is a floating point type.

For example:

template <typename T>
struct is_floating_point
{
    static const bool value;
};

template <typename T>
const bool is_floating_point<T>::value =
    std::numeric_limits<T>::is_specialized &&  // Is fundamental arithmetic type...
    !std::numeric_limits<T>::is_integer;       // ...that is not an integer

Altri suggerimenti

Since there are only three floating point types (per C++98 §3.9.1/8), it's not hard to enumerate them:

template <typename T>
struct is_floating_point {
  enum { value = 0 };
};

template <>
struct is_floating_point<float> {
  enum { value = 1 };
};

template <>
struct is_floating_point<double> {
  enum { value = 1 };
};

template <>
struct is_floating_point<long double> {
  enum { value = 1 };
};

Something along the lines of your is_integral trick:

#include <limits>
#include <iostream>

template <typename T>
struct is_floating_point
{
  static const bool value;
};

// is a fundamental type (i.e. not a user defined type) but not an integer
template <typename T>
const bool is_floating_point<T>::value =
!std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_bounded;

struct Obj
{
};

int main()
{
    std::cout << is_floating_point<float>::value << std::endl;        // 1
    std::cout << is_floating_point<int>::value << std::endl;          // 0
    std::cout << is_floating_point<Obj>::value << std::endl;          // 0
    std::cout << is_floating_point<bool>::value << std::endl;         // 0
    std::cout << is_floating_point<double>::value << std::endl;       // 1
    std::cout << is_floating_point<long double>::value << std::endl;  // 1

    // this would compile since it's an array of size 1
    int Y[is_floating_point<float>::value] = { };
    // this wouldn't compile since it's an array of size 0
    int N[is_floating_point<int>::value] = { };
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top