constexpr vs constinit

C++ 20 constexpr & constinit

constinit allows initializating the object in constant time and then modifying it at runtime:

constinit std::string global = {"Test"};
//constinit std::string global = runtimeFunc(); doesn't compile
constexpr std::string global2 = {"Test"};

int main() {
    global = "abc";
    //global2 = "test"; doesn't compile
}

1. Object lifetimes explanation

constexpr object requires:

  • static object
  • constexpr constructor
  • constexpr destructor

(constexpr constructor & destructor) -> tipo literal

constinit object requires:

  • static object
  • constexpr constructor

constinit compiles & constexpr does not compile:

class A {
    int a;
    char b;

    public:
    ~A() {
        this->a = 0;
        this->b = 0;
    }

    constexpr A() {
        this->a = 1;
        this->b = 1;
    }
};

int
main(int  __attribute__((unused))  argc,
     char __attribute__((unused)) *argv[],
     char __attribute__((unused)) *envp[])
{
    std::cout << "A created" << std::endl;
    {
        constinit static A test;
        // constexpr static A test2; does not compile
    }
    std::cout << "A destroyed" << std::endl;

    return 0;
}

constinit compiles & constexpr compiles:

class A {
    int a;
    char b;

    public:
    constexpr ~A() {
        this->a = 0;
        this->b = 0;
    }

    constexpr A() {
        this->a = 1;
        this->b = 1;
    }
};

int
main(int  __attribute__((unused))  argc,
     char __attribute__((unused)) *argv[],
     char __attribute__((unused)) *envp[])
{
    std::cout << "A created" << std::endl;
    {
        constinit static A test;
        constexpr static A test2;
    }
    std::cout << "A destroyed" << std::endl;

    return 0;
}