constexpr 的限制

字面类型要求

参数和返回类型必须是字面类型。字面类型包括:

  • 基本类型(int、char、bool等)
  • 引用类型(必须绑定到字面类型)
  • 数组类型(元素必须是字面类型)
  • 字面值类(所有非静态成员为字面类型,且有constexpr构造函数)
  • void(C++14起)
  • 部分标准库类型(如std::array、std::string_view)

非字面类型示例:

  • std::string(动态内存分配)
  • 带有虚函数的类(C++20前)
  • 包含非字面类型成员的类
禁止的操作
  • 动态内存分配(new/delete)
  • 异常处理(throw或try-catch)
  • 调用非constexpr函数
  • 修改全局/静态变量
成员函数的特殊规则
  • 虚函数:C++20前不允许,C++20起允许
  • 隐式const限定:C++11中constexpr成员函数隐式为const,C++14取消此限制
递归深度限制

编译器对constexpr递归深度有默认限制(如GCC默认为512层),可通过编译选项调整:

g++ -fconstexpr-depth=1000 main.cpp

版本差异
特性C++11C++14+C++20
函数体复杂度单条语句允许循环进一步扩展
虚函数支持不支持不支持支持
成员函数隐式const是否否
示例对比

合法(C++14+):

constexpr int sum(int n) {
    int total = 0;
    for (int i = 0; i < n; ++i) {
        total += i;
    }
    return total;
}

非法:

constexpr int* create() {
    int* p = new int(10); // 动态内存分配
    return p;
}

合法(C++20):

struct Base {
    virtual constexpr int get() { return 1; }
};

更多推荐