0

0

C++如何使用std::disjunction实现类型逻辑或?(模板约束)

穿越時空

穿越時空

发布时间:2026-03-03 09:38:30

|

893人浏览过

|

来源于php中文网

原创

std::disjunction 是编译期类型计算工具,必须用于 requires 表达式或 static_assert 中,参数须为继承自 std::integral_constant 的类型特征类(如 std::is_integral),不可用 _v 版本或值类型;使用时需配合 ::value 或 _v 别名(如 std::disjunction_v)以满足 concept 对布尔常量表达式的要求。

c++如何使用std::disjunction实现类型逻辑或?(模板约束)

std::disjunction 在 C++20 模板约束里怎么写才不报错

它不是运行时函数,不能直接调用;它是编译期类型计算工具,必须用在 requires 表达式或 static_assert 里,否则会触发 SFINAE 失败或硬错误。

  • std::disjunction 接收的是类型模板参数(比如 std::is_integral_v<t></t> 是值,不能直接塞进去;得用 std::is_integral<t></t>
  • 常见误写:std::disjunction<:is_integral_v>></:is_integral_v> → 错,_v 版本是布尔值,不是类型
  • 正确写法:std::disjunction<:is_integral>, std::is_enum<t>></t></:is_integral>,每个参数都必须是带 ::value 的类型特征类(即继承自 std::integral_constant 的类型)
  • 如果混入非类型(比如 bool 字面量),编译器通常报 template argument 1 is invalid 或类似 no type named 'type'

和 requires (A || B) 直接写逻辑或有啥区别

本质一样,但语义和错误提示不同:直接写 requires std::is_integral_v<t> || std::is_enum_v<t></t></t> 更简洁,而 std::disjunction 主要用于需要“延迟求值”或组合已有 trait 类型的场景。

  • 直接 ||requires 中可读性高,编译器报错时通常能准确定位哪个子句失败
  • std::disjunction 必须配合 ::value 使用,比如 requires std::disjunction_v<:is_integral>, std::is_enum<t>></t></:is_integral>(注意 _v 后缀)
  • 如果你封装了一个复合 trait,比如 template<typename t> using is_arith_or_enum = std::disjunction<:is_arithmetic>, std::is_enum<t>></t></:is_arithmetic></typename>,那复用性比重复写 || 更干净
  • 性能无差异 —— 全是编译期计算,生成的代码完全一致

为什么有时候 std::disjunction_v 编译不过,但 std::conjunction_v 可以

不是实现问题,而是你传进去的类型里有“未定义行为”的 trait 实例 —— 比如对 void、引用、数组等非法类型做 std::is_class,在 std::disjunction 中可能提前触发实例化失败。

Music Muse
Music Muse

Create professional music with Music Muse's AI song generator.

下载
  • std::disjunction 是短路逻辑,但 C++ 模板实例化不保证短路:所有模板实参仍会被检查是否有效类型
  • 典型翻车点:std::disjunction<:is_class>, std::is_integral<t>></t></:is_class> 遇到 T = void 时,std::is_class<void></void> 合法,但 std::is_integral<void></void> 是 ill-formed,整个表达式失败
  • 解决办法:先用 std::is_valid(C++20 std::is_detected 替代方案)包裹,或改用 requires + || 让约束本身参与 SFINAE
  • 简单验证:把每个 trait 单独放进 static_assert 看是否崩,就能定位哪个类型不兼容

在 concept 定义里用 std::disjunction 容易漏掉什么

容易忽略 std::disjunction 返回的是类型,不是布尔值;concept 要求的是布尔常量表达式,所以必须取 ::value 或用 _v 别名。

立即学习C++免费学习笔记(深入)”;

  • 错:concept ArithOrPtr = std::disjunction<:is_arithmetic>, std::is_pointer<t>>;</t></:is_arithmetic> → 缺少 ::value,编译器报 concept definition requires a boolean constant expression
  • 对:concept ArithOrPtr = std::disjunction_v<:is_arithmetic>, std::is_pointer<t>>;</t></:is_arithmetic>
  • 更安全写法:用 requires 显式展开,避免嵌套过深导致错误信息模糊,例如:concept ArithOrPtr = requires(T t) { requires std::is_arithmetic_v<t> || std::is_pointer_v<t>; };</t></t>
  • 别依赖 IDE 的自动补全——有些老版本 clangd 会把 std::disjunction 当成函数建议,补全成括号调用,一粘贴就红
实际用的时候,最麻烦的不是语法,是当约束链变长后,编译错误堆栈里根本看不出是哪个 std::is_* 在捣鬼。宁可多拆几个小 concept,也别一股脑塞进一个 std::disjunction

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java中boolean的用法
java中boolean的用法

在Java中,boolean是一种基本数据类型,它只有两个可能的值:true和false。boolean类型经常用于条件测试,比如进行比较或者检查某个条件是否满足。想了解更多java中boolean的相关内容,可以阅读本专题下面的文章。

366

2023.11.13

java boolean类型
java boolean类型

本专题整合了java中boolean类型相关教程,阅读专题下面的文章了解更多详细内容。

42

2025.11.30

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1561

2023.10.24

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

186

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

125

2025.11.27

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

186

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

125

2025.11.27

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

431

2023.07.18

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

48

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 10.5万人学习

C 教程
C 教程

共75课时 | 5.1万人学习

C++教程
C++教程

共115课时 | 20.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号