requires表达式是C++20标准中概念(Concepts)特性里的核心语法结构,它的主要作用是在编译阶段对模板参数或者普通表达式进行约束检查,判断其是否满足预设的条件,从而让模板的约束规则更直观、更易维护,替代了以往SFINAE机制繁琐的写法。

requires表达式的核心含义
从本质上来说,requires表达式是一个编译期的谓词,它的求值结果是一个布尔常量。如果requires表达式内部的所有约束条件都满足,那么整个表达式的值为true,否则为false。它不会生成运行时的任何代码,仅用于编译期的类型检查和约束匹配。
比如我们需要判断一个类型是否支持加法操作,就可以用requires表达式来检测,不需要再写复杂的类型萃取代码。
requires表达式的基本定义形式
requires表达式的基础语法结构如下:
requires (参数列表) {
约束条件1;
约束条件2;
// 可以有多个约束条件
}
其中参数列表是可选的,约束条件可以是合法的表达式、类型声明、嵌套的requires表达式等。下面介绍几种常见的定义场景。
1. 无参数的简单requires表达式
如果不需要依赖模板参数,只是检查某个固定的条件,可以省略参数列表:
#include <iostream>
#include <type_traits>
// 检查int是否是整型
constexpr bool is_int = requires {
std::is_integral<int>::value;
};
int main() {
std::cout << is_int << std::endl; // 输出1,因为int是整型
return 0;
}
2. 带模板参数的requires表达式
最常见的用法是结合模板参数,对模板的类型参数进行约束:
#include <iostream>
#include <concepts>
// 定义一个requires表达式,检查类型T是否支持+操作
template <typename T>
concept Addable = requires (T a, T b) {
a + b; // 约束条件:T类型的两个对象可以做加法
};
// 只有满足Addable约束的类型才能调用这个函数
template <Addable T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(1, 2) << std::endl; // 合法,int满足Addable约束
// std::cout << add(std::cout, std::cout) << std::endl; // 编译报错,ostream不满足Addable约束
return 0;
}
3. 包含类型约束的requires表达式
除了检查表达式合法性,还可以在requires表达式里声明类型,判断某个类型是否存在:
#include <iostream>
#include <vector>
// 检查类型T是否有value_type成员类型
template <typename T>
concept HasValueType = requires {
typename T::value_type; // 类型约束:T必须包含value_type这个成员类型
};
int main() {
std::cout << HasValueType<std::vector<int>> << std::endl; // 输出1,vector有value_type
std::cout << HasValueType<int> << std::endl; // 输出0,int没有value_type
return 0;
}
4. 带嵌套requires表达式的复合约束
如果约束条件比较复杂,可以在requires表达式内部嵌套另一个requires表达式,实现多层约束:
#include <iostream>
#include <concepts>
// 检查类型T是否可以转换为U类型
template <typename T, typename U>
concept ConvertibleTo = requires (T val) {
requires std::convertible_to<T, U>; // 嵌套requires表达式,使用标准库的convertible_to概念
};
int main() {
std::cout << ConvertibleTo<int, double> << std::endl; // 输出1,int可以转换为double
std::cout << ConvertibleTo<int, std::ostream> << std::endl; // 输出0,int不能转换为ostream
return 0;
}
requires表达式的使用注意事项
- requires表达式的所有检查都在编译期完成,不会生成任何运行时开销。
- 约束条件中的表达式不需要是完整的可执行语句,只要语法合法即可,比如
a + b不需要赋值给某个变量。 - 如果requires表达式的参数列表中的参数是未命名的,也可以直接写类型,比如
requires (std::vector<int>)也是合法的。 - requires表达式可以和
if constexpr结合使用,在模板函数内部做分支选择:
#include <iostream>
#include <vector>
template <typename T>
void print_size(T t) {
if constexpr (requires { t.size(); }) {
std::cout << "size: " << t.size() << std::endl;
} else {
std::cout << "no size method" << std::endl;
}
}
int main() {
std::vector<int> v = {1,2,3};
print_size(v); // 输出size: 3
print_size(10); // 输出no size method
return 0;
}
C++requires表达式概念约束模板修改时间:2026-07-24 09:15:31