..
// Example 2: Understanding constexpr/consteval Functions
// These functions run at COMPILE TIME and return results the compiler can use
#include <iostream>
// ==========================================
// CONSTEXPR: Function evaluated at compile time
// ==========================================
// Regular function - runs at runtime
bool isDogRuntime(const char* type) {
return type[0] == 'D'; // Check if starts with 'D'
}
// Constexpr function - can run at compile time!
constexpr bool isDogCompileTime(const char* type) {
return type[0] == 'D';
}
// Consteval (C++20) - MUST run at compile time
consteval bool isDogMustCompileTime(const char* type) {
return type[0] == 'D';
}
// ==========================================
// Animal types
// ==========================================
struct Dog {
static constexpr const char* type = "marearts.com Dog";
};
struct Cat {
static constexpr const char* type = "marearts.com Cat";
};
struct Bird {
static constexpr const char* type = "marearts.com Bird";
};
// ==========================================
// Using constexpr functions with "if constexpr"
// ==========================================
template <typename T>
void describeAnimal() {
// if constexpr - evaluated at COMPILE TIME
if constexpr (isDogCompileTime(T::type)) {
std::cout << "This is a DOG - has 4 legs, barks\n";
}
else if constexpr (T::type[0] == 'C') { // Can use any compile-time expression
std::cout << "This is a CAT - has 4 legs, meows\n";
}
else {
std::cout << "This is a BIRD - has 2 legs, flies\n";
}
}
// ==========================================
// Difference: regular if vs if constexpr
// ==========================================
template <typename T>
void regularIf() {
// Regular if - runs at RUNTIME, all branches must be valid
if (isDogRuntime(T::type)) {
std::cout << "Runtime check: Dog\n";
}
}
template <typename T>
void constexprIf() {
// if constexpr - evaluated at COMPILE TIME, only chosen branch exists
if constexpr (isDogCompileTime(T::type)) {
std::cout << "Compile-time check: Dog\n";
}
}
// ==========================================
// Main
// ==========================================
int main() {
std::cout << "=== Using constexpr functions with 'if constexpr' ===\n\n";
describeAnimal<Dog>();
describeAnimal<Cat>();
describeAnimal<Bird>();
std::cout << "\n=== Difference between regular if and if constexpr ===\n\n";
regularIf<Dog>();
constexprIf<Dog>();
// With constexpr, the check happens at COMPILE TIME!
// The compiler removes the unused branches - they don't even exist in final code!
return 0;
}
/*
KEY POINTS:
1. constexpr/consteval functions run at COMPILE TIME
2. "if constexpr" uses compile-time checks
3. Only the chosen branch exists in final code (very efficient!)
4. Can't use constexpr functions in "requires" clauses - they need concepts
5. But CAN use constexpr functions in "if constexpr" - that's the dispatcher pattern!
*/
..
------------------------------------------------------------
How to build
> g++ -std=c++20 02_constexpr_functions.cpp -o 02_constexpr_functions
>./02_constexpr
=== Using constexpr functions with 'if constexpr' ===
This is a DOG - has 4 legs, barks
This is a CAT - has 4 legs, meows
This is a BIRD - has 2 legs, flies
=== Difference between regular if and if constexpr ===
Runtime check: Dog
Compile-time check: Dog
------------------------------------------------------------------------------------------------------------------------
### 2. Constexpr Functions (02_constexpr_functions.cpp)
**What it teaches:** Functions that run at compile time
```cpp
// Constexpr function - evaluated at compile time
constexpr bool isDog(const char* type) {
return type[0] == 'D';
}
// Use in if constexpr
template <typename T>
void describe() {
if constexpr (isDog(T::type)) { // ✅ Function works here!
std::cout << "It's a dog!";
}
}
```
OK then what is different constexpr and consteval and anything else?
Can run at compile time OR runtime, depending on context:Flexible: The compiler decides when to evaluate it.MUST run at compile time - stricter than constexpr:Strict: Compile error if it can't be evaluated at compile time.Ensures variables are initialized at compile time (doesn't apply to functions):Bonus: if constexpr (C++17)
Not a function specifier, but a compile-time conditional statement:So the answer is: three main keywords (constexpr, consteval, constinit), plus if constexpr for compile-time conditionals! 🎯
ok, one thing to clear
The only requirement for if constexpr is that the condition must be a compile-time constant expression - it doesn't matter whether it comes from a function call or is written inline! 🎯
What is meaning constexpr is flexible??
constexpr - Flexible (Can do both)
This same function can be used in BOTH ways:✅ Use 1: Compile-time evaluation
✅ Use 2: Runtime evaluation
consteval - NOT Flexible (Compile time only)
This can ONLY be used at compile time:"Flexible" = The compiler decides when to evaluate it based on context! 🎯
One more thing to clear!! what happened in runtime exactly?
When you call a constexpr function with runtime values, it simply executes as a regular function during program execution.Think of constexpr like this:
Compile Time (if arguments are constants):Runtime (if arguments are not constants):So yes, constexpr with runtime values = normal function execution! 🎯
That's it.
Thank you!
Study.marearts.com!!!
No comments:
Post a Comment