C++中的requires表达式是什么意思?如何定义?

来源:PHP编程网作者:半糖头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++中的requires表达式是什么意思?如何定义?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++中的requires表达式是什么意思?如何定义?》有用,将其分享出去将是对创作者最好的鼓励。

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

C++中的requires表达式是什么意思?如何定义?

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

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。