【C++】编译期if

1. 背景

template<typename T>
void foo(T t) {
    if (std::is_same_v<T,int>) 
    {
        std::cout << "int\n";
    } 
    else if(std::is_same_v<T,double>)
    {
        std::cout <<"double\n";
    }
}

上面这段代码无法通过编译。

2. if constexpr

使用编译期if,模板实例化时,false分支将被丢弃不参与模板实例化,但注意仍然会检查语法正确性,若语法不对也还是会编译不过。

template<typename T>
void foo(T t) {
    if constexpr(std::is_same_v<T,int>) 
    {
        std::cout << "int\n";
    } 
    else if constexpr(std::is_same_v<T,double>)
    {
        std::cout <<"double\n";
    }
}

3. 应用场景

针对模板参数的类型/数值等,在编译期决定“这段源码要不要参与编译”,从而避免运行期分支、避免实例化无效代码。

  • 按类型裁剪代码(最常见)
if constexpr (std::is_pointer_v<T>)  
  *t = 0;
else                                 
  std::sort(t.begin(), t.end());
  • 按数值裁剪代码
template<int N>
auto fact() {
    if constexpr (N <= 1) return 1;
    else return N * fact<N-1>();
}
* 按编译期布尔常量裁剪
constexpr bool use_fast_path = sizeof(void*) == 8;
if constexpr (use_fast_path) { /* AVX2 版本 */ }
else                         { /* 标量版本 */ }
  • 避免实例化无效成员函数
template<typename T>
struct S {
    void serialize() const {
        if constexpr (Serializable<T>) { /* … */ }
        else static_assert(always_false<T>, "T must be serializable");
    }
};
  • 替代 #ifdef 的“类型安全版本”
    不需要预处理器,可直接利用 if constexpr (PLATFORM_WINDOWS) 等常量表达式。

4. 与预处理if endif对比

#if 0

#endif

预处理属于纯文本处理,不检查语法,内部代码即使有语法错误也不会影响编译。
if constexpr是不参与模板实例化,但会检查语法。

posted @ 2025-08-30 11:53  仰望星河Leon  阅读(2)  评论(0)    收藏  举报