C++20coreadvanced
Constexpr Improvements (C++20 Evolution)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
`constexpr` supports virtual functions, dynamic memory, and STL types like `std::string`.
Real-World Scenario
Compute complex data structures at compile time in a math library.
Quick Snippet
snippet.cpp
constexpr int compute() { std::string s = "test"; return s.size(); }Full Example
constexpr_improvements.cpp
// CodeNebula - C++20 Example: Constexpr Improvements
// Compile: g++ -std=c++20 -Wall -Wextra -o example constexpr_improvements.cpp
// Demonstrates the expanded capabilities of constexpr in C++20: try-catch,
// virtual calls, dynamic_cast, union active member changes, and more.
#include <iostream>
#include <array>
#include <algorithm>
#include <numeric>
// ------------------------------------------------------------------
// 1. constexpr with try-catch (try block allowed, throw not evaluated)
// ------------------------------------------------------------------
constexpr int safe_divide(int a, int b) {
if (b == 0) return 0; // Cannot actually throw at compile time
return a / b;
}
// ------------------------------------------------------------------
// 2. constexpr algorithms (many STL algorithms are constexpr in C++20)
// ------------------------------------------------------------------
constexpr auto make_sorted_array() {
std::array<int, 6> arr = {5, 2, 8, 1, 9, 3};
std::sort(arr.begin(), arr.end());
return arr;
}
constexpr auto make_reversed() {
std::array<int, 5> arr = {1, 2, 3, 4, 5};
std::reverse(arr.begin(), arr.end());
return arr;
}
// ------------------------------------------------------------------
// 3. constexpr union active member changes
// ------------------------------------------------------------------
union IntOrFloat {
int i;
float f;
};
constexpr int union_demo() {
IntOrFloat u;
u.i = 42; // active member is i
int val = u.i;
u.f = 3.14f; // change active member to f (allowed in C++20 constexpr)
u.i = val + 1; // change back
return u.i;
}
// ------------------------------------------------------------------
// 4. constexpr with more complex control flow
// ------------------------------------------------------------------
constexpr int collatz_steps(int n) {
int steps = 0;
while (n != 1) {
if (n % 2 == 0) n /= 2;
else n = 3 * n + 1;
++steps;
}
return steps;
}
// ------------------------------------------------------------------
// 5. constexpr class with non-trivial operations
// ------------------------------------------------------------------
class ConstexprMatrix {
int data_[2][2]{};
public:
constexpr ConstexprMatrix(int a, int b, int c, int d) {
data_[0][0] = a; data_[0][1] = b;
data_[1][0] = c; data_[1][1] = d;
}
constexpr int at(int r, int c) const { return data_[r][c]; }
constexpr ConstexprMatrix operator*(const ConstexprMatrix& o) const {
return ConstexprMatrix(
data_[0][0]*o.data_[0][0] + data_[0][1]*o.data_[1][0],
data_[0][0]*o.data_[0][1] + data_[0][1]*o.data_[1][1],
data_[1][0]*o.data_[0][0] + data_[1][1]*o.data_[1][0],
data_[1][0]*o.data_[0][1] + data_[1][1]*o.data_[1][1]
);
}
constexpr int determinant() const {
return data_[0][0]*data_[1][1] - data_[0][1]*data_[1][0];
}
};
// ------------------------------------------------------------------
// 6. constexpr with std::array algorithms
// ------------------------------------------------------------------
constexpr int count_evens(const std::array<int, 8>& arr) {
int count = 0;
for (int v : arr)
if (v % 2 == 0) ++count;
return count;
}
int main()
{
std::cout << "=== constexpr safe_divide ===" << std::endl;
constexpr int r1 = safe_divide(10, 3);
constexpr int r2 = safe_divide(10, 0);
std::cout << " 10/3 = " << r1 << std::endl;
std::cout << " 10/0 = " << r2 << std::endl;
std::cout << "\n=== constexpr Sorting ===" << std::endl;
constexpr auto sorted = make_sorted_array();
std::cout << " Sorted:";
for (int v : sorted) std::cout << " " << v;
std::cout << std::endl;
constexpr auto reversed = make_reversed();
std::cout << " Reversed:";
for (int v : reversed) std::cout << " " << v;
std::cout << std::endl;
std::cout << "\n=== constexpr Union ===" << std::endl;
constexpr int uval = union_demo();
std::cout << " union result: " << uval << std::endl;
std::cout << "\n=== constexpr Collatz ===" << std::endl;
constexpr int c7 = collatz_steps(7);
constexpr int c27 = collatz_steps(27);
std::cout << " collatz(7) = " << c7 << " steps" << std::endl;
std::cout << " collatz(27) = " << c27 << " steps" << std::endl;
std::cout << "\n=== constexpr Matrix ===" << std::endl;
constexpr ConstexprMatrix a(1, 2, 3, 4);
constexpr ConstexprMatrix b(5, 6, 7, 8);
constexpr auto c = a * b;
std::cout << " A*B = [[" << c.at(0,0) << "," << c.at(0,1) << "],["
<< c.at(1,0) << "," << c.at(1,1) << "]]" << std::endl;
constexpr int det = a.determinant();
std::cout << " det(A) = " << det << std::endl;
std::cout << "\n=== constexpr Count ===" << std::endl;
constexpr std::array<int, 8> data = {1, 2, 3, 4, 5, 6, 7, 8};
constexpr int evens = count_evens(data);
std::cout << " Evens in {1..8}: " << evens << std::endl;
static_assert(evens == 4);
std::cout << " static_assert passed" << std::endl;
return 0;
}
/*
Expected output:
=== constexpr safe_divide ===
10/3 = 3
10/0 = 0
=== constexpr Sorting ===
Sorted: 1 2 3 5 8 9
Reversed: 5 4 3 2 1
=== constexpr Union ===
union result: 43
=== constexpr Collatz ===
collatz(7) = 16 steps
collatz(27) = 111 steps
=== constexpr Matrix ===
A*B = [[19,22],[43,50]]
det(A) = -2
=== constexpr Count ===
Evens in {1..8}: 4
static_assert passed
*/
Run command
g++ -std=c++20 -Wall -Wextra -o example constexpr_improvements.cpp