Why is std::array<T,N>::size() not declared static?

153 views Asked by At

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());
}
0

There are 0 answers