Nikos Athanasiou
Nikos Athanasiou

Reputation: 31549

is_integral vs is_integer: is one of them redundant?

is_integral and is_integer seem to answer the same thing in the same way.

From the links to the related documentation pages, is_integral seems to be missing specializations for the following types

signed char       
unsigned char     
unsigned short    
unsigned int      
unsigned long     
unsigned long long

Yet a compiled example, shows (of course) their identical behaviour on those types as well:

#include <iostream>
#include <type_traits>
using namespace std;

int main() 
{
    cout << is_integral<signed char       >::value << endl;
    cout << is_integral<unsigned char     >::value << endl;
    cout << is_integral<unsigned short    >::value << endl;
    cout << is_integral<unsigned int      >::value << endl;
    cout << is_integral<unsigned long     >::value << endl; 
    cout << is_integral<unsigned long long>::value << endl;
    return 0;
}

So if they also behave the same, what was the point of introducing both of them in C++11?

So if they also behave the same, what was the point of introducing both of them in c++11 ?

Edit : rephrasings

As Useless points out, the phrase including any signed, unsigned, and cv-qualified variants from the is_integral doc page reveals that even their specifications are a complete match.

Upvotes: 23

Views: 2135

Answers (4)

Jonathan Wakely
Jonathan Wakely

Reputation: 171383

Noone has mentioned the point that std::is_integral follows the same style as the other C++11 UnaryTypeTraits of defining a single static data member called value. That allows it to be used interchangeably where any unary type trait is needed, for example:

template<typename Cond1, typename Cond2>
  using And = integral_constant<bool, Cond1::value && Cond2::value>;

You can't use std::numeric_limits::is_integer in the same way, because it doesn't follow the same conventions as the C++11 traits.

Splitting each trait into a single type with consistent names makes them more flexible than a trait that bundles several properties together with unpredictable names.

Upvotes: 5

quantdev
quantdev

Reputation: 23813

Both are identical and will provide the same outputs.

However std::numeric_limits<T>::is_integer exists since C98, not C++11, whereas std::is_integral was introduced as part of the C++11 type traits (<type_traits> header)

Edit:

As mentioned by @Useless , the reason of the introduction of std::is_integral is probably the desire to regroup all traits in <type_traits>.

Upvotes: 4

Josh Kelley
Josh Kelley

Reputation: 58382

Here's the original proposal to add is_integral to C++0x.

They make no reference of the overlap with std::numeric_limits<>::is_integer, but I'm assuming that the desire was simply to have all type traits in a single obvious place.

Upvotes: 3

Useless
Useless

Reputation: 67772

std::numeric_limits<T>::is_integer was not introduced by C++11. It was just updated to use the new constexpr qualifier.

std::is_integral<T> was introduced by C++11, and you're right it gives the same results. As to why it was added - possibly because the integral-ness or otherwise of a type isn't logically part of that type's numeric_limits?

It seems to be the goal of the <type_traits> header to gather all the type classification helpers in one place, while the older numeric_limits collects only properties specific to, well, numbers. If numeric_limits<T>::is_integer were deprecated, there'd be a slightly arbitrary boundary which type traits lived in <type_traits>, and which were considered numerical. It's hardly a terrible duplication to have it in both places.

Upvotes: 20

Related Questions