C++14coreintermediate
Relaxed constexpr Restrictions
C++14 · Modern Refined · Compiler flag: -std=c++14
Explanation
C++14 significantly relaxes the rules for `constexpr` functions compared to C++11. Functions may now contain local variables, loops, multiple `return` statements, `if`/`switch` branches, and mutation of local state, enabling real algorithms to execute at compile time.
Real-World Scenario
A compile-time lookup table generator computes CRC-32 values for all 256 byte values using loops and bitwise operations, eliminating the need for an external code-generation step.
Quick Snippet
snippet.cpp
#include <iostream>
#include <array>
constexpr int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; ++i)
result *= i;
return result;
}
constexpr auto build_table() {
std::array<int, 10> table{};
for (int i = 0; i < 10; ++i)
table[i] = factorial(i);
return table;
}
int main() {
constexpr auto table = build_table();
for (auto v : table) std::cout << v << " ";
// 1 1 2 6 24 120 720 5040 40320 362880
}Full Example
relaxed_constexpr.cpp
// CodeNebula - C++14 Example: Relaxed constexpr
// Compile: g++ -std=c++14 -Wall -Wextra -o example relaxed_constexpr.cpp
// Demonstrates relaxed constexpr restrictions in C++14. Functions marked
// constexpr can now contain loops, local variables, if/else, switch, and
// multiple return statements. In C++11, constexpr was limited to a single
// return expression. Real-world use: compile-time algorithms, lookup tables,
// hash functions, and mathematical computations.
#include <iostream>
#include <array>
// ------------------------------------------------------------------
// 1. constexpr with loops and local variables (impossible in C++11)
// ------------------------------------------------------------------
constexpr int factorial(int n)
{
int result = 1;
for (int i = 2; i <= n; ++i)
result *= i;
return result;
}
// ------------------------------------------------------------------
// 2. constexpr with if/else and multiple returns
// ------------------------------------------------------------------
constexpr int fibonacci(int n)
{
if (n <= 0) return 0;
if (n == 1) return 1;
int a = 0, b = 1;
for (int i = 2; i <= n; ++i)
{
int temp = a + b;
a = b;
b = temp;
}
return b;
}
// ------------------------------------------------------------------
// 3. constexpr with switch statement
// ------------------------------------------------------------------
constexpr const char* day_name(int day)
{
switch (day)
{
case 0: return "Sunday";
case 1: return "Monday";
case 2: return "Tuesday";
case 3: return "Wednesday";
case 4: return "Thursday";
case 5: return "Friday";
case 6: return "Saturday";
default: return "Invalid";
}
}
// ------------------------------------------------------------------
// 4. constexpr GCD using Euclidean algorithm with a loop
// ------------------------------------------------------------------
constexpr int gcd(int a, int b)
{
while (b != 0)
{
int temp = b;
b = a % b;
a = temp;
}
return a;
}
// ------------------------------------------------------------------
// 5. constexpr string length (pointer iteration)
// ------------------------------------------------------------------
constexpr int str_length(const char* s)
{
int len = 0;
while (s[len] != '\0')
++len;
return len;
}
int main()
{
// ------------------------------------------------------------------
// Compile-time evaluations (used as template args / array sizes)
// ------------------------------------------------------------------
constexpr int fact5 = factorial(5);
constexpr int fib10 = fibonacci(10);
constexpr int g = gcd(48, 18);
constexpr int slen = str_length("Hello, C++14!");
// Array size from constexpr result proves compile-time evaluation
std::array<int, fact5> arr{}; // array of 120 elements
std::cout << "=== Constexpr with Loops ===" << std::endl;
std::cout << " factorial(5) = " << fact5 << std::endl;
std::cout << " factorial(10) = " << factorial(10) << std::endl;
std::cout << " Array size = " << arr.size() << " (proves compile-time)" << std::endl;
std::cout << std::endl;
std::cout << "=== Constexpr Fibonacci ===" << std::endl;
std::cout << " fibonacci(10) = " << fib10 << std::endl;
std::cout << " fibonacci(20) = " << fibonacci(20) << std::endl;
std::cout << std::endl;
std::cout << "=== Constexpr Switch ===" << std::endl;
for (int d = 0; d < 7; ++d)
std::cout << " Day " << d << ": " << day_name(d) << std::endl;
std::cout << std::endl;
std::cout << "=== Constexpr GCD ===" << std::endl;
std::cout << " gcd(48, 18) = " << g << std::endl;
std::cout << " gcd(100, 75) = " << gcd(100, 75) << std::endl;
std::cout << std::endl;
std::cout << "=== Constexpr String Length ===" << std::endl;
std::cout << " strlen(\"Hello, C++14!\") = " << slen << std::endl;
return 0;
}
/*
Expected output:
=== Constexpr with Loops ===
factorial(5) = 120
factorial(10) = 3628800
Array size = 120 (proves compile-time)
=== Constexpr Fibonacci ===
fibonacci(10) = 55
fibonacci(20) = 6765
=== Constexpr Switch ===
Day 0: Sunday
Day 1: Monday
Day 2: Tuesday
Day 3: Wednesday
Day 4: Thursday
Day 5: Friday
Day 6: Saturday
=== Constexpr GCD ===
gcd(48, 18) = 6
gcd(100, 75) = 25
=== Constexpr String Length ===
strlen("Hello, C++14!") = 13
*/
Run command
g++ -std=c++14 -Wall -Wextra -o example relaxed_constexpr.cpp