Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling new in a constexpr function

I am trying to write a factory function that creates a constexpr object that uses new. Is this even possible? The following code does not compile:

aa.cpp: In function ‘int main()’: aa.cpp:23:39: in ‘constexpr’ expansion of ‘((Buffer*)(& b))->Buffer::~Buffer()’ aa.cpp:10:36: error: deallocation of already deallocated storage 10 |
constexpr ~Buffer() { delete[] data; }

#include <random>
struct Buffer {
    int size;
    int* data;

    constexpr Buffer(int n) : size(n), data(new int[n])
    {
        for (int i = 0; i < n; ++i) data[i] = i;
    }

    constexpr ~Buffer() { delete[] data; }

    constexpr int get(int i) const { return data[i]; }
    static constexpr Buffer Create(int n)
    {
        Buffer buf(n);
        // ...
        return buf; 

    }
};

constexpr void test(int d)
{
    Buffer b2(d);
}

int main() {
    constexpr Buffer b = Buffer::Create(4);
    constexpr Buffer b2(43); // also does not compile: error: ‘Buffer(43)’ is not a constant expression because it refers to a result of ‘operator new’
    test(rand()); // This is Ok
}

like image 966
DuduArbel Avatar asked Jun 17 '26 08:06

DuduArbel


2 Answers

While constexpr does allow certain uses of operator new, it does not allow storing the result of operator new for use at runtime (more specifically, the new memory must be deleted in the same compile-time expression).

Think about it: how would a compile-time heap allocation be usable at runtime?

You can use heap allocations at compile-time only, or at runtime only. Not a mix of both for the same allocation.

Here is a valid example:

struct Buffer {
    constexpr Buffer(int n)
    {
        int* data = new int[n];
        for (int i = 0; i < n; ++i)
            data[i] = i;
        delete[] data;
    }
};
like image 106
John Zwinck Avatar answered Jun 19 '26 21:06

John Zwinck


You can't create a constexpr object that requires dynamically allocated memory. You can allocate memory in a constexpr context, but you must release it before the constexpr context ends.

As for test(rand()); // This is Ok, it's not actually executed at compile time. constexpr function is not guaranteed to be executed at compile time unless it's used to initialize a constexpr variable.

like image 34
許恩嘉 Avatar answered Jun 19 '26 20:06

許恩嘉