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

1

9

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"
);
Aculeate answered 24/6, 2017 at 22:33 Comment(2)
Can you give an example of exactly how/where you want to "detect and branch"? I'm guessing something inside a template, rather than for a fixed type like char[20], for which we all know the answer?Tenne
Define "detecting and branching". The purpose of static_assert is, indeed, to issue a compilation error if the assertion fails. If you need a different result, you have to explain what it is.Cassidycassie
H
4

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&

Hiroshima answered 24/6, 2017 at 23:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.