In the following snippet, an static assert passes and the other one fails:
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
Tip: Remove the comment to debug the type (it is correctly deduced to be int [5]
).
Why is this? Tested on clang trunk.
I'd guess it has something to do with arrays decaying into pointers.. somehow.
Solution: use std::remove_reference_t
, Rng
will be int (&)[5]
, this is a reference to an array, and not an array.
Xeo added:
template<class> struct dump;
dump<decltype(r)>{};
will fail to compile and reveal the correct type of r
.
The int**** j = r;
produced a wrong error (saying can't assing int[5]
to int****
).
The type of Rng
is int (&)[5]
which is a reference to an array (and not an array) and hence std::is_array
returns false_type
.
One can remove the reference (e.g. using std::remove_reference_t
) to make it work as you expected.