检测某些非数字类型T的std :: numeric :: type <T>的特化

Rob*_*mey 7 c++ limits numeric

我想检查一个类型是否在std :: numeric_limits中有一个条目.当类型是数组 - (或者可能不是数字?)时,我得到编译器错误.这使我无法根据std :: numeric_limits中是否支持该类型来检测和分支.我很感激任何想要分享的见解.

// 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"
);
Run Code Online (Sandbox Code Playgroud)

Cur*_*ous 4

发生这种情况是因为如果您查看内部std::numeric_limits或查看文档,您将看到如下所示的方法声明

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;
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,有些函数按T值返回,而 C++ 不支持按值返回数组类型(请参阅为什么 C++ 不支持返回数组的函数?

所以下面的行将无法编译

std::numeric_limits<char[20]>::is_specialized
Run Code Online (Sandbox Code Playgroud)

并且任何直接使用 SFINAE 直接检查is_specialized类型是否适用的进一步尝试都将无法编译,因为会产生一个不在模板的直接上下文中的错误(因为返回数组类型,如上所述)。因此,您需要检查支持的概念std::numeric_limits(在本例中std::is_arithmetic

然而,要使这项工作起作用,您需要做的就是std::decay_t类型

std::numeric_limits<std::decay_t<char[20]>>::is_specialized
Run Code Online (Sandbox Code Playgroud)

现在它可以工作了,因为您已经显式地将数组类型衰减为指针并且可以从函数返回。您可能一开始就想这样做,因为您不想意外调用std::numeric_limits::is_specialized像这样的非腐烂类型const int&