В следующем фрагменте статическое утверждение проходит, а другое не выполняется:
template <class Rng> constexpr bool is_array(Rng&& r) {
// int*** debug = r; // uncomment this to debug r's type
return std::is_array<Rng>{};
// return std::is_array<decltype(r)>{}; // fails too
}
int a[5] = {0, 1, 2, 3, 4};
static_assert(std::is_array<decltype(a)>{}, ""); // passes
static_assert(is_array(a), ""); // fails
Подсказка: удалите комментарий для отладки типа (он правильно выводится как int [5]
).
Почему это? Проверено на лязг ствола.
Я предполагаю, что это как-то связано с массивами, распадающимися на указатели … как-то.
Решение: использовать std::remove_reference_t
, Rng
будет int (&)[5]
, это ссылка на массив, а не массив.
Xeo добавил:
template<class> struct dump;
dump<decltype(r)>{};
не сможет скомпилировать и раскрыть правильный тип r
,
int**** j = r;
выдал неправильную ошибку int[5]
в int****
).
Тип Rng
является int (&)[5]
которая является ссылкой на массив (а не массив) и, следовательно, std::is_array
возвращается false_type
,
Можно удалить ссылку (например, используя std::remove_reference_t
) чтобы все работало так, как вы ожидали.