Why do two different ways of writing C++ constexpr produce different results?

8 hours ago 2
ARTICLE AD BOX

I understand that constexpr can compute results at compile time. Therefore, I'd like to try using compile-time computation to obtain a table of prime numbers.

Below is the code that I've managed to compile after multiple attempts.

#include <vector> #include <algorithm> #include <print> #include <array> //Returns a std::array containing all prime numbers in the range [1, n]. template<int n> consteval auto get_primes(){ auto inner_get_primes = []() constexpr { auto vis = std::vector<bool>(n + 1, false); auto primes = std::vector<int>(); for(int i = 3; i <= n; i += 2) { // Skip all even numbers if(not vis[i]){ primes.push_back(i); } for(int j = 0; j < primes.size() and primes[j] <= n / i; j++){ vis[i * primes[j]] = true; if(i % primes[j] == 0) break; } } return primes; }; auto result = std::array<int, inner_get_primes().size() + 1>{2}; auto primes = inner_get_primes(); std::copy(primes.begin(), primes.end(), result.begin() + 1); return result; } int main(){ constexpr int n = 400; constexpr auto primes = get_primes<n>(); std::println("the count of primes in [1, {}] = {}", n, primes.size()); std::println("primes = {}", primes); }

In the code above, I had to call inner_get_primes() twice. When I tried the following code, the compiler gave me an error.

#include <vector> #include <algorithm> #include <print> #include <array> //Returns a std::array containing all prime numbers in the range [1, n]. template<int n> consteval auto get_primes(){ auto inner_get_primes = []() constexpr { auto vis = std::vector<bool>(n + 1, false); auto primes = std::vector<int>(); for(int i = 3; i <= n; i += 2) { // Skip all even numbers if(not vis[i]){ primes.push_back(i); } for(int j = 0; j < primes.size() and primes[j] <= n / i; j++){ vis[i * primes[j]] = true; if(i % primes[j] == 0) break; } } return primes; }; constexpr auto primes = inner_get_primes(); auto result = std::array<int, primes.size() + 1>{2}; std::copy(primes.begin(), primes.end(), result.begin() + 1); return result; } int main(){ constexpr int n = 400; constexpr auto primes = get_primes<n>(); std::println("the count of primes in [1, {}] = {}", n, primes.size()); std::println("primes = {}", primes); }

The output of compiler is:

[Error]‘inner_get_primes.get_primes<400>()::<lambda()>()’ is not a constant expression because it refers to a result of ‘operator new’

This makes me very confused. Although primers holds the dynamically allocated memory at compile time, that memory is released when result is returned.

Why isn't this allowed?

Read Entire Article