Обнаружение специализации std::numeric::type‹T› для некоторого нечислового типа T

Я хочу проверить, есть ли у типа запись в 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"
);

person Robert Ramey    schedule 24.06.2017    source источник
comment
Можете ли вы привести пример того, как и где вы хотите обнаружить и разветвить? Я предполагаю, что что-то внутри шаблона, а не для фиксированного типа, такого как char[20], для которого мы все знаем ответ?   -  person aschepler    schedule 25.06.2017
comment
Определение обнаружения и ветвления. Цель static_assert действительно состоит в том, чтобы выдать ошибку компиляции, если утверждение не выполняется. Если вам нужен другой результат, вы должны объяснить, что это такое.   -  person Sam Varshavchik    schedule 25.06.2017


Ответы (1)


Это происходит потому, что если вы заглянете внутрь 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;

Здесь, как вы можете видеть, есть функции, которые возвращают T по значению, а C++ не поддерживает возврат типов массивов по значению (см. Почему C++ не поддерживает функции, возвращающие массивы?)

Таким образом, следующая строка не будет компилироваться

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

И любая дальнейшая попытка напрямую проверить, работает ли is_specialized для типа непосредственно с помощью SFINAE, не будет скомпилирована, потому что будет произведена ошибка (из-за возврата типов массива, как описано выше), которая не находится в непосредственном контексте шаблона. Таким образом, вам нужно проверить концепцию, которая поддерживается для std::numeric_limits (в данном случае std::is_arithmetic)

Однако все, что вам нужно сделать, это std::decay_t тип

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

И теперь это будет работать, потому что вы явно преобразовали тип массива в указатель, который можно вернуть из функции. Вы, вероятно, хотели сделать это в первую очередь, потому что вы не хотите случайно вызвать std::numeric_limits::is_specialized для неразрушенного типа, такого как const int&

person Curious    schedule 24.06.2017