Using C++20 MinGW and MSVC, I encountered - at least for me - unexpected behaviour.
Writing this boiled down and seemingly senseless static_assert code compiled fine:
void functionArray(std::array<uint8_t, 2> const data)
{
static_assert(2 == data.size());
}
Whereas this code did not:
void functionArray(std::array<uint8_t, 2> const & data)
{
static_assert(2 == data.size());
}
error C2131: expression did not evaluate to a constant
A solution with the current C++ capabilities seems to be to use std::tuple_size's special overload for std::array:
void functionArray(std::array<uint8_t, 2> const & data)
{
static_assert(2 == std::tuple_size<std::remove_reference<decltype(data)>::type>{});
}
MSVC implements std::array<T,N>::size() as:
template <class _Ty, size_t _Size>
class array { // fixed size array of values
public:
_NODISCARD constexpr size_type size() const noexcept {
return _Size;
}
};
Why is (& std::array<T,N>)::size() not evaluated at compile time?
Is it because the reference to a std::array instance itself is not a constexpr variable, and so the implicit this in the member function call prevents compile time evaluation (see e.g. here)?
Why is std::array<T,N>::size() not declared static?
The following example shows that this would solve the problem described above:
#include <cstddef>
template <size_t N>
struct Blub
{
static constexpr size_t size()
{
return N;
}
};
void blubFunction(Blub<4> const & blub)
{
static_assert(4 == blub.size());
}