【C++】 constexpr
contexpr
1. constexpr变量
1对于修饰的变量而言,const并未区分出编译常量和运行常量;constexpr限定在编译器常量。
2. constexpr函数
#include <iostream>
#include <array>
using namespace std;
constexpr int foo(int i)
{
return i + 5;
}
int main()
{
int i = 10;
std::array<int, foo(5)> arr; // OK
foo(i); // Call is Ok
}
constexpr修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。但是,传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了。不过,我们不必因此而写两个版本,所以如果函数体适用于constexpr函数的条件,可以尽量加上constexpr。
而检测constexpr函数是否产生编译时期值的方法很简单,就是利用std::array需要编译期常值才能编译通过的小技巧。这样的话,即可检测你所写的函数是否真的产生编译期常值了。
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>
// 普通 if - 运行时判断
void runtime_if_example() {
bool condition = true;
if (condition) {
std::cout << "运行时条件为真" << std::endl;
} else {
std::cout << "运行时条件为假" << std::endl;
}
}
// if constexpr - 编译时判断
template<typename T>
void compile_time_if_example() {
if constexpr (std::is_integral_v<T>) {
std::cout << "T 是整数类型" << std::endl;
// 只有当 T 是整数类型时,这段代码才会被编译
T value = 42;
std::cout << "整数值: " << value << std::endl;
} else if constexpr (std::is_floating_point_v<T>) {
std::cout << "T 是浮点类型" << std::endl;
T value = 3.14;
std::cout << "浮点值: " << value << std::endl;
} else {
std::cout << "T 是其他类型" << std::endl;
// 对于其他类型的处理
T value{};
std::cout << "默认构造的值" << std::endl;
}
}
// 展示 if constexpr 的威力:避免编译错误
template<typename T>
void safe_operation() {
if constexpr (std::is_arithmetic_v<T>) {
// 只有算术类型才能进行数学运算
T result = T{} + T{1};
std::cout << "算术运算结果: " << result << std::endl;
} else {
// 非算术类型使用其他操作
std::cout << "非算术类型,跳过数学运算" << std::endl;
}
}
// 使用示例
int main() {
std::cout << "=== 运行时 if 示例 ===" << std::endl;
runtime_if_example();
std::cout << "\n=== 编译时 if constexpr 示例 ===" << std::endl;
compile_time_if_example<int>();
compile_time_if_example<double>();
compile_time_if_example<std::string>();
std::cout << "\n=== 安全操作示例 ===" << std::endl;
safe_operation<int>();
safe_operation<double>();
safe_operation<std::string>();
return 0;
}