2

Edit: This now errors on godbolt (gcc, msvc) with non-empty initialization. There was some confusion because my msvc was erroring with empty initialization when godbolt wasn't (probably because my msvc is more recent).

#include <vector>

constexpr std::size_t f() {
    constexpr std::vector<int> v{ 1 };
    return 1;
}

int main() {
    constexpr auto a = f();
}

With /std:c++latest

ConsoleApplication9.cpp(12,24): error C2131: expression did not evaluate to a constant ConsoleApplication9.cpp(12,24): message : (sub-)object points to memory which was heap allocated during constant evaluation

Edit: gcc warning with non-empty initialization explains the problem

error: 'std::vector(std::initializer_list{((const int*)(& const int [1]{1})), 1}, std::allocator())' is not a constant expression because it refers to a result of 'operator new' 195 | return static_cast<_Tp*>(::operator new(__n)); | ~~~~~~~~~~~~~~^~~~~

Tom Huntington
  • 2,260
  • 10
  • 20

1 Answers1

3

The std::vector shouldn't have had the constexpr specifier https://stackoverflow.com/a/69498591/11998382. The following works

constexpr std::size_t f() {
    std::vector<int> aaa{};
    return 1;
}

I think godbolt was wrong to compile this. (if you never allocate then its okay) constexpr functions can evaluate at runtime, but the std::vector can't be constexpr in the runtime version of this function

Tom Huntington
  • 2,260
  • 10
  • 20
  • 2
    This doesn't sound right. Both GCC, Clang, and MSVC on Godbolt accept your code. I don't see why `constexpr` wouldn't be allowed on that variable. The linked answer says it's forbidden to preserve an `std::vector` from compile-time to runtime, but you're not doing that. – HolyBlackCat Apr 05 '23 at 23:07
  • @HolyBlackCat if the function was executing at runtime, then with the `constexpr` specifier the `std::vector` would be preserved from compile to runtime. Well that was my thinking. But the GCC and Clang compiler implementers know more than me so ... – Tom Huntington Apr 05 '23 at 23:40
  • 1
    I'm talking about preserving its memory (the elements). E.g. making the vector a global `constexpr` variable and computing the elements at compile-time. Since the variable would still exist at runtime, that would be an error. – HolyBlackCat Apr 06 '23 at 06:56
  • @HolyBlackCat so I was right, but only when something is actually allocated on the vector – Tom Huntington Apr 06 '23 at 23:47
  • What? Your case is different: the vector is either used entirely at runtime or entirety at compile-time, both are fine. – HolyBlackCat Apr 07 '23 at 06:16