C++ constexpr Lambda | 'Compile-Time Lambda' Guide
이 글의 핵심
C++ constexpr Lambda: "Compile-Time Lambda" Guide. Constexpr lambda basics and compile-time calculation.
Introduction
C++17 constexpr lambda is a lambda expression executable at compile-time. Used for metaprogramming, compile-time calculation, type validation, etc., providing powerful features without runtime cost.
1. constexpr Lambda Basics
C++17 Implicit constexpr
#include <iostream>
// C++17: lambda implicitly constexpr
auto add = [](int a, int b) {
return a + b;
};
int main() {
// Compile-time use
constexpr int result1 = add(3, 4); // 7
static_assert(add(3, 4) == 7);
// Runtime use also possible
int x = 10, y = 20;
int result2 = add(x, y); // 30
std::cout << result1 << ", " << result2 << std::endl;
return 0;
}
Key Concepts:
- From C++17, lambdas are implicitly constexpr
- Condition: lambda body satisfies
constexprrequirements - Usable at both compile-time and runtime
Explicit constexpr
// Explicitly specify constexpr
constexpr auto square = [](int x) constexpr {
return x * x;
};
constexpr int result = square(5); // 25
static_assert(square(5) == 25);
// Use as array size
int arr[square(4)]; // Size 16
2. Compile-Time Calculation
Example 1: Factorial
#include <iostream>
constexpr auto factorial = [](int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
};
int main() {
// Compile-time calculation
constexpr int f5 = factorial(5); // 120
static_assert(factorial(5) == 120);
// Use as array size
int arr[factorial(4)]; // Size 24
std::cout << "5! = " << f5 << std::endl;
std::cout << "Array size: " << sizeof(arr) / sizeof(int) << std::endl;
return 0;
}
Example 2: Power (Using Template)
#include <iostream>
template<int N>
constexpr auto power = [](int base) {
int result = 1;
for (int i = 0; i < N; i++) {
result *= base;
}
return result;
};
int main() {
constexpr int p2 = power<3>(2); // 2^3 = 8
constexpr int p3 = power<5>(3); // 3^5 = 243
static_assert(power<3>(2) == 8);
static_assert(power<5>(3) == 243);
std::cout << "2^3 = " << p2 << std::endl;
std::cout << "3^5 = " << p3 << std::endl;
return 0;
}
Example 3: Array Initialization
#include <array>
#include <iostream>
template<size_t N>
constexpr auto makeArray = []() {
std::array<int, N> arr{};
for (size_t i = 0; i < N; i++) {
arr[i] = i * i;
}
return arr;
};
int main() {
constexpr auto squares = makeArray<5>();
// {0, 1, 4, 9, 16}
for (int val : squares) {
std::cout << val << " ";
}
std::cout << std::endl;
return 0;
}
3. Type Checking and Metaprogramming
Type Checking
#include <type_traits>
#include <iostream>
constexpr auto isIntegral = [](auto value) {
return std::is_integral_v<decltype(value)>;
};
constexpr auto isFloating = [](auto value) {
return std::is_floating_point_v<decltype(value)>;
};
int main() {
static_assert(isIntegral(10));
static_assert(!isIntegral(3.14));
static_assert(isFloating(3.14));
static_assert(!isFloating(10));
std::cout << "Type check passed" << std::endl;
return 0;
}
Conditional Compilation
#include <type_traits>
#include <iostream>
constexpr auto processValue = [](auto value) {
if constexpr (std::is_integral_v<decltype(value)>) {
return value * 2;
} else if constexpr (std::is_floating_point_v<decltype(value)>) {
return value * 1.5;
} else {
return value;
}
};
int main() {
constexpr int i = processValue(10); // 20
constexpr double d = processValue(10.0); // 15.0
static_assert(i == 20);
static_assert(d == 15.0);
std::cout << i << ", " << d << std::endl;
return 0;
}
4. Constraints
What’s Allowed
// ✅ Allowed: basic operations
constexpr auto add = [](int a, int b) { return a + b; };
// ✅ Allowed: loops
constexpr auto sum = [](int n) {
int result = 0;
for (int i = 1; i <= n; i++) {
result += i;
}
return result;
};
// ✅ Allowed: recursion
constexpr auto fibonacci = [](int n) {
auto fib = [](int n, auto& self) -> int {
if (n <= 1) return n;
return self(n - 1, self) + self(n - 2, self);
};
return fib(n, fib);
};
// ✅ Allowed: capture (C++17)
constexpr int x = 10;
constexpr auto addX = [x](int y) { return x + y; };
What’s Not Allowed
Here is the nonConstexpr implementation:
// ❌ Not allowed: non-constexpr function call
int nonConstexpr(int x) { return x * 2; }
constexpr auto bad1 = [](int x) {
return nonConstexpr(x); // Error
};
// ❌ Not allowed: static variable (C++17)
constexpr auto bad2 = []() {
static int count = 0; // Error
return count++;
};
// ❌ Not allowed: dynamic allocation
constexpr auto bad3 = []() {
int* p = new int(10); // Error
delete p;
return 0;
};
// ❌ Not allowed: I/O
constexpr auto bad4 = []() {
std::cout << "Hello"; // Error
return 0;
};
Summary
Key Points
- C++17 constexpr lambda: Implicitly constexpr
- Compile-time calculation: No runtime cost
- Type checking: Powerful with type_traits
- Metaprogramming: Template + lambda combination
- Constraints: No I/O, dynamic allocation
When to Use
✅ Use constexpr lambda when:
- Need compile-time calculation
- Metaprogramming
- Type validation
- Performance optimization
❌ Don’t use when:
- Need I/O operations
- Dynamic allocation required
- Too complex (readability matters)
Best Practices
- ✅ Use for compile-time calculation
- ✅ Combine with templates
- ✅ Use for type checking
- ❌ Don’t overuse (readability first)
- ❌ Don’t use for side effects
Related Articles
Master compile-time programming with constexpr lambda! 🚀
Frequently Asked Questions (FAQ)
Q. When would I use this in practice?
A. Everything about C++ constexpr Lambda : from basic concepts to practical applications.
Q. What should I read before this?
A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the C++ series index for the full picture.
Q. Where can I study this more deeply?
A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.
Related Articles (Internal Links)
Other articles related to this topic.
- C++ 컴파일 타임 프로그래밍 | constexpr·consteval·if constexpr 완벽 가이드
- C++ constexpr 함수 | ‘컴파일 타임 함수’ 가이드
- C++ if constexpr | ‘컴파일 타임 if’ 가이드
Keywords Covered in This Article (Related Search Terms)
This article covers C++, lambda, constexpr, C++17, compile-time.