2026-09-29 · 1 min read · c++

The nth prime

The nth prime for n below 100 in modern C++, built at compile time and checked at run time.

#include <array>
#include <cstddef>
#include <optional>
#include <print>

// The 99th prime is 523, so a sieve up to 523 covers every n below 100.
inline constexpr std::size_t max_n = 99;
inline constexpr std::size_t sieve_limit = 523;

consteval auto first_primes() {
    std::array<int, max_n> primes{};
    std::array<bool, sieve_limit + 1> composite{};
    std::size_t found = 0;
    for (std::size_t i = 2; i <= sieve_limit && found < primes.size(); ++i) {
        if (composite[i]) continue;
        primes[found++] = static_cast<int>(i);
        for (std::size_t j = i * i; j <= sieve_limit; j += i) composite[j] = true;
    }
    return primes;
}

inline constexpr auto table = first_primes();

/// The nth prime, counting from 1, or nothing when n is outside 1..99.
[[nodiscard]] constexpr std::optional<int> nth_prime(std::size_t n) noexcept {
    if (n == 0 || n > table.size()) return std::nullopt;
    return table[n - 1];
}

static_assert(nth_prime(1) == 2);
static_assert(nth_prime(25) == 97);
static_assert(nth_prime(99) == 523);
static_assert(!nth_prime(100));

int main() {
    for (std::size_t n : {1uz, 10uz, 25uz, 99uz, 100uz}) {
        if (auto p = nth_prime(n)) std::println("prime #{} is {}", n, *p);
        else std::println("prime #{} is out of range (1 to 99 only)", n);
    }
}

The primes are found once, while the compiler builds the program, by a sieve in a consteval function, so looking one up is just an array read. nth_prime returns std::optional instead of a magic value when n is out of range, and the static_asserts check the table before the program ever runs. Try changing n in main, or edit the sieve, then press run.

← All snippets