Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting specialization of std::numeric::type<T> for some non numeric type T

I want to check to see if a type has an entry in std::numeric_limits. When the type is an array - (or perhaps not a number?) I get a compiler error. This prevents me from detecting and branching based on whether the type is supported in std::numeric_limits. I would appreciate any insight anyone wants to share.

// the following provokes compiler error on Clang
// Function cannot return array type 'type' (aka 'char [20]')
static_assert(
    ! std::numeric_limits<char[20]>::is_specialized,
    "! std::numeric_limits<char[20]>::is_specialized"
);
// invokes static assert on compile as expected
static_assert(
    std::numeric_limits<char[20]>::is_specialized,
    "std::numeric_limits<char[20]>::is_specialized"
);
like image 730
Robert Ramey Avatar asked Jun 24 '17 22:06

Robert Ramey


1 Answers

This happens because if you take a look inside std::numeric_limits or take a look at the documentation you will see declarations of methods like the following

template<class T>
class numeric_limits
{
public:
    static constexpr bool is_specialized = false;
    static constexpr T min() noexcept;
    static constexpr T max() noexcept;
    static constexpr T lowest() noexcept;

Here as you can see there are functions that return T by value, and C++ does not support returning array types by value (see Why doesn't C++ support functions returning arrays?)

So the following line will not compile

std::numeric_limits<char[20]>::is_specialized

And any further attempt to directly check whether is_specialized works for a type directly with SFINAE will not compile because there will be an error produced (because of returning array types as explained above) that is not in the immediate context of the template. So you would need to inspect the concept that is supported for std::numeric_limits (in this case std::is_arithmetic)

However all you need to do here to make this work is to std::decay_t the type

std::numeric_limits<std::decay_t<char[20]>>::is_specialized

And now it will work because you have explicitly decayed the array type into a pointer and that is returnable from the function. You probably wanted to do that in the first place because you don't want to accidentally call std::numeric_limits::is_specialized for a non decayed type like const int&

like image 56
Curious Avatar answered Sep 24 '22 19:09

Curious