'How to get std array size in a constant expression?

Consider this code:

#include <array>
#include <cstddef>

struct A {
    std::array<std::size_t, 4> test;
    void method() {
        std::size_t duptest[test.size()] = {}; // error: variable-sized object may not be initialized
    }
};

Godbolt Clang

It fails under Clang with the error in the comment. I don't understand why this is considered a VLA, because test.size is a constexpr function. How do I stop duptest from being interpreted as a VLA?



Solution 1:[1]

test means this->test, and evaluating this.size() must first evaluate this->test. But this is not a constant expression so test.size() is not a constant expression, even though std::array::size is constexpr and it doesn't use test. Therefore this is a VLA and is nonstandard.

You might use std::tuple_size.

size_t duptest[std::tuple_size<decltype(test)>()] = {};

Solution 2:[2]

The problem is that the expression test.size() is equivalent to this->test.size() but the this object is more of a run-time construct. In particular, in standard C++ the size of an array must be a compile-time constant(aka constant expression) which the expression this->test.size() is not. From expr.const#2:

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

  • this, except in a constexpr function or a constexpr constructor that is being evaluated as part of e;

Now in your example, this appears inside the member function method but the member function method is neither constexpr nor it is being evaluated as part of the expression this->test.size().

Therefore this->test.size() cannot be used to specify the size of the array since that expression is not a compile-time constant.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2