std::requires 不存在,c++20 中真正的约束关键字是 requires(无 std:: 前缀),用于模板声明中限制参数类型,配合 concept 实现编译期约束与重载决议,而非运行时断言。

std::requires 是什么,它能做什么
std::requires 不是标准库里的函数或类型,而是 C++20 引入的 约束关键字(constraint keyword),必须配合 concept 使用。单独写 std::requires 会编译失败——根本不存在这个符号。常见误解是把它当成类似 static_assert 的工具,但它的作用域只在模板声明中,用于约束模板参数是否满足条件。
正确写法:用 requires 关键字 + concept 或内联约束
真正起作用的是 requires(无命名空间前缀),不是 std::requires。它出现在模板参数列表后、函数签名前,用来施加约束:
template<typename t>
requires std::integral<t> // ✅ 正确:使用标准 concept
T add(T a, T b) { return a + b; }
<p>template<typename t>
T multiply(T a, T b) requires std::floating_point<t> { // ✅ C++20 允许这种后置写法
return a * b;
}</t></typename></p></t></typename>
- 不能写
std::requires std::integral<t></t>—— 编译器报错:error: 'requires' is a keyword -
requires后面跟的是布尔表达式,通常是 concept 检查、decltype推导或自定义逻辑,但不能是任意运行时表达式 - 前置写法(
template<...> requires ...</...>)和后置写法(... requires ...)语义等价,但后置更易读,尤其对单个函数
常见错误:把 requires 当成 if 或 static_assert
有人试图这样写来“做编译期判断”:
template<typename t>
void foo() {
if constexpr (std::is_integral_v<t>) { /* ... */ } // ✅ 这才是编译期分支
// ❌ 错误:
// requires std::is_integral_v<t>; // 语法错误:requires 不是语句
// static_assert(std::is_integral_v<t>); // ✅ 可行,但用途不同:失败时硬报错,不参与重载决议
}</t></t></t></typename>
-
requires只在模板声明/定义处有效,不能出现在函数体内 - 它控制的是 模板是否参与重载候选,不是“断言失败就停”,而是“不匹配就忽略”——这是和
static_assert的本质区别 - 如果多个重载都带
requires,且只有一个满足,就选它;都不满足则编译失败(SFINAE 失效)
复杂点:嵌套 requires 和布尔组合容易写错
多个条件组合时,括号和逻辑运算符优先级容易出问题:
template<typename t>
requires (std::integral<t> && sizeof(T)
T compress(T x) { /* ... */ }</t></typename>
- 必须用括号明确分组,否则
&&和||可能绑定错误(C++ 中&&优先级高于||) - 不要写
requires std::integral<t> || std::floating_point<t></t></t>—— 这看起来合理,但若T是std::string,两个都假,整个约束失败,不会 fallback 到其他重载 - 更安全的做法是拆成多个重载,或用自定义 concept 封装逻辑,避免长表达式
真正难的不是语法,而是想清楚:你到底要“排除不合法类型”,还是“主动选择最匹配的实现”——前者用 requires,后者往往需要 if constexpr 配合。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











