Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Size of reference to std::array not available at compiletime

I'm interested to know why the second static_assert in my code below doesn't work. It seems like even though the array c is a reference to a, the size of the array is embedded in the type, so it should be available at compile time.

#include <array>

int main()
{
    std::array<int,2> a = {1,2};
    std::array<int,2> b = {2,3};
    std::array<int,2>& c = a;

    static_assert(a.size() == b.size(), "a.size==b.size"); // ok size of array is compile time constant
    static_assert(c.size() == a.size(), "c.size==a.size"); // compiler error "static_assert expression is not an integral constant expression"
}
like image 705
Jacob Merson Avatar asked Aug 09 '20 21:08

Jacob Merson


People also ask

Does the size of the array have to be determined at compile time?

c. The size of an array is determined at compile time. Hence, the given statement is “True”. The size of an array is determined at compile time.

Is std :: array fixed size?

std::array is a container that encapsulates fixed size arrays. This container is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member. Unlike a C-style array, it doesn't decay to T* automatically.

Is size of array should be known at compile time in C?

yes it works in gcc, my doubt was why it works but it seems now newer version of C allows this as pointed out by others..

What is the purpose of std :: array?

std::array provides many benefits over built-in arrays, such as preventing automatic decay into a pointer, maintaining the array size, providing bounds checking, and allowing the use of C++ container operations.


2 Answers

the size of the array is embedded in the type, so it should be available at compile time.

This is true. But regardless, c is not a constant expression and therefore expression that contains it as a subexpression cannot be a constant expression - except certain operators that interact only with the type of the operand such as sizeof.

You can get the size for example using:

static_assert(
    std::tuple_size<
        std::remove_reference_t<decltype(c)>
    >::value == a.size(),
    "c.size==a.size"
);

Unfortunately, it is not very pretty.

like image 136
eerorika Avatar answered Sep 20 '22 21:09

eerorika


Note, that if you move all declaration out of main function, code would compile. Why? Because a is automatic variable, so it's not really a compile time object and reference is not elided here, therefore neither a nor cor c.size() are constexpr. For global variables location of a can be determined at compile time.

IF you try bind them within function like this:

constexpr std::array<int,2> a = {1,2};
std::array<int,2> b = {2,3};
constexpr const std::array<int,2>& c = a;

You'll get error that a is not a constant expression. Variant which still may compile:

#include <array>

std::array<int,2> a = {1,2};
std::array<int,2> b = {2,3};

int main()
{
    std::array<int,2>& c = a;

    static_assert(a.size() == b.size(), "a.size==b.size"); 
    static_assert(c.size() == a.size(), "c.size==a.size"); 
}
like image 26
Swift - Friday Pie Avatar answered Sep 23 '22 21:09

Swift - Friday Pie