You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写仅接受constexpr实参的constexpr函数?

如何编写仅接受constexpr实参的constexpr函数?

你遇到的这个问题,其实是C++里constexpr函数的一个典型痛点——普通的constexpr函数,哪怕你传的实参是constexpr的,函数里的参数本身也不会被当作编译期常量来用。这是因为constexpr函数允许在运行时调用,编译器得保留这种可能性,所以不会默认把参数视为编译期可用的。

不过在C++20里,有个完美的解决方案:consteval立即函数。

consteval是C++20新增的特性,它强制函数必须在编译期完成求值,完全禁止运行时调用。这意味着所有传入的实参必须是编译期常量,而且在函数内部,你可以放心地把参数当作constexpr来使用——比如用来指定std::array的大小,这正是你需要的场景。

针对你的代码,直接改造一下就能用:

#include <array>
#include <string_view>

constexpr std::array easy{'h', 'e', 'l', 'l', 'o'};
constexpr struct Hard {
    constexpr Hard(int n) : size_(n) {}
    size_t size_;
    constexpr size_t size() const { return size_; }
} hard(10);
constexpr std::string_view nope{"hello"};

// 用consteval替代原来的constexpr模板函数
consteval auto f(auto s) {
    return std::array<char, s.size()>();
}

auto arr_easy = f(easy);    // 完全正常编译
auto arr_hard = f(hard);    // 没问题!hard是constexpr,consteval确保s在编译期可用
auto arr_nope = f(nope);    // 也能正常工作!nope的size()会被编译期计算

为什么这个方案能解决你的所有问题?

  • consteval函数的调用必须是编译期常量表达式,所以编译器会直接拒绝任何非constexpr实参的调用,完美实现“只接受constexpr实参”的需求。
  • 在函数内部,参数s会被当作编译期常量处理,所以s.size()可以安全地用作std::array的模板参数(毕竟模板参数要求必须是编译期常量)。
  • 对比你之前尝试的非类型模板参数方案,consteval完全没有类型限制——不管是std::array、你自定义的Hard,还是std::string_view,只要实参是constexpr的,就能正常传递和使用。

如果你的项目还不能升级到C++20,那情况会麻烦一些:

  • 对于像std::array、自定义Hard这类可以作为非类型模板参数的类型,你可以继续用模板方案;
  • 对于std::string_view这类不支持非类型参数的类型,可能只能单独处理(比如手动指定大小),或者用宏来强制编译期上下文调用,但这些方案都远不如consteleg优雅。

所以如果编译器支持C++20,consteval绝对是最优解,完全匹配你的需求。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 10:38:03