I was trying to compute an array in compilation time to speed up some functions while i encountered an error which I was unable to resolve with the help of cppreference.
The code boils down to this:
#include <cstddef>
#include <array>
template<typename T, size_t size>
constexpr auto giveArray()
{
std::array<T, size> arr;
for(size_t i = 0; i < size; ++i)
arr[i] = 0;
return arr;
}
constexpr auto arr = giveArray<int,10>().data();
While compiling with: "$ g++ -std=c++20 code.cpp" on ubuntu i get the error that .data() is not a constexpr function while it definitely is. Why am i getting this error and how it can be fixed while still running this function in compilation time and storing only a pointer, not the std::array object?
3
Answers
You can’t.
The rules of C++ are not suspended just because your code executes at compile time (indeed, not suspending those rules is half the point of
constexpr
code). The array needs to exist in order for a pointer to it to be meaningful. That means the array object needs to continue to be around when someone uses that pointer.Getting a pointer to a temporary that gets destroyed will leave that pointer pointing to a destroyed object. This is just as true in compile-time code as runtime code. And using that pointer is just as non-functional at compile-time as it would be at runtime. Indeed, it’s less functional, as UB (which is what accessing that pointer will provoke) at compile-time must be diagnosed and turned into a compile error.
You can try with
I mean… whith
you try to initialize
arr
with a pointer to memory that is set free immediately after.You can solve fixing the
std::array
received fromgiveArray()
so
arr
receive a pointer to a memory that remain stable after the initializationTo initialize a
constexpr
variable you need an initializer that is a constant expression. ButgiveArray<int,10>().data();
is not a constant expression.From here :
The expression
giveArray<int,10>().data();
has the value category of prvalue , so it is not a glvalue expression. That means it has to be "a prvalue core constant expression whose value satisfies the following constraints" to be a constant expression. Since the expression evaluates to a pointer type, it has to meet this condition :In this case, it is none of those things so it is not a constant expression. However, if you change the code to like :
my_array
is a global variable, which implies it has static storage duration.data()
returns a pointer to that storage, which makes it a constant expression.In short, this rule makes it so you can’t have a pointer with an invalid pointer value when executing code at compile time.