Search code examples
c++visual-c++c++20constexprstdstring

C++20 constexpr vector and string not working


I'm getting a strange compiler error when trying to create constexpr std::string and std::vector objects:

#include <vector>
#include <string>

int main()
{
    constexpr std::string cs{ "hello" };
    constexpr std::vector cv{ 1, 2, 3 };
    return 0;
}

The compiler complains that "the expression must have a constant value":

compiler error

Am I missing something? I am using the latest Microsoft Visual Studio 2019 version: 16.11.4, and the reference (https://en.cppreference.com/w/cpp/compiler_support) states that constexpr strings and vectors are supported by this compiler version:

enter image description here

I have also tried the constexpr std::array, which does work. Could the issue have anything to do with the dynamic memory allocation associated with vectors?


Solution

  • Your program is actually ill-formed, though the error may be hard to understand. constexpr allocation support in C++20 is limited - you can only have transient allocation. That is, the allocation has to be completely deallocated by the end of constant evaluation.

    So you cannot write this:

    int main() {
        constexpr std::vector<int> v = {1, 2, 3};
    }
    

    Because v's allocation persists - it is non-transient. That's what the error is telling you:

    <source>(6): error C2131: expression did not evaluate to a constant
    <source>(6): note: (sub-)object points to memory which was heap allocated during constant evaluation
    

    v can't be constant because it's still holding on to heap allocation, and it's not allowed to do so.

    But you can write this:

    constexpr int f() {
        std::vector<int> v = {1, 2, 3};
        return v.size();
    }
    
    static_assert(f() == 3);
    

    Here, v's allocation is transient - the memory is deallocated when f() returns. But we can still use a std::vector during constexpr time.