模板编程中实现 SFINAE(Substitution Failure Is Not An Error)

在C++模板编程中,std::enable_if 是一个常用的工具,它依赖于 SFINAE(Substitution Failure Is Not An Error)原则来控制模板的启用或禁用。理解 std::enable_if 如何工作,可以更清楚地看到为什么 disable_if_same_or_derived 在某些情况下等同于 void 类型。

std::enable_if 的工作原理

std::enable_if 是一个模板,它的作用是根据条件在编译期决定是否启用某个模板。如果条件为 true,它定义一个内部类型 type,通常被设定为 void。如果条件为 false,则没有定义 type,从而导致模板匹配失败。这利用了 SFINAE 原则,即在模板匹配过程中如果替换失败不会导致编译错误,而是简单地从候选模板集中移除。

代码解释

template<typename A, typename B>
using disable_if_same_or_derived = typename std::enable_if<!std::is_base_of<A, typename std::remove_reference<B>::type>::value
>::type;

这段代码使用 std::enable_ifstd::is_base_of 来定义一个条件性的类型别名 disable_if_same_or_derived

  1. std::is_base_of<A, typename std::remove_reference<B>::type>::value
    • 检查 A 是否是(去掉引用后的)B 的基类,或 A 是否与 B 相同。
  2. !std::is_base_of<...>::value
    • 取反操作,即当 A 不是 B 的基类,并且 A 不等于 B 时,条件为 true
  3. std::enable_if<condition>::type
    • 当条件为 true 时,std::enable_if 定义 type 成员类型,通常被设定为 void

为什么等同于 void 类型

在条件为 true 时,即 A 不是 B 的基类并且 A 不等于 B 时:

typename std::enable_if<true>::type

在这种情况下,std::enable_if<true> 会定义一个成员类型 type,默认情况下为 void。因此,disable_if_same_or_derived 在这种情况下等同于 void

using disable_if_same_or_derived = void;

在条件为 false 时,即 AB 的基类或 A 等于 B 时:

typename std::enable_if<false>::type

在这种情况下,std::enable_if<false> 不会定义 type,因此模板匹配失败,不会实例化。

示例应用

考虑以下函数模板,它使用 disable_if_same_or_derived 来控制模板实例化:

#include <type_traits>
#include <iostream>template<typename A, typename B>
using disable_if_same_or_derived = typename std::enable_if<!std::is_base_of<A, typename std::remove_reference<B>::type>::value>::type;class Base {};
class Derived : public Base {};template<typename T, typename = disable_if_same_or_derived<Base, T>>
void foo(T&&) {std::cout << "foo(T&&) called" << std::endl;
}// Overload to handle Base and its derived types
void foo(Base&) {std::cout << "foo(Base&) called" << std::endl;
}int main() {int i = 0;Base b;Derived d;foo(i);    // 调用 foo(T&&)foo(b);    // 调用 foo(Base&)foo(d);    // 调用 foo(Base&)
}

在这个例子中:

  • 当传递的类型不是 Base 或其派生类时,例如 int 类型,disable_if_same_or_derived 等同于 void,函数模板 foo(T&&) 可以被实例化。
  • 当传递的类型是 Base 或其派生类时,例如 BaseDerived 类型,disable_if_same_or_derived 无法定义类型,导致模板匹配失败,而选择重载函数 foo(Base&)

这种方式可以用于实现函数重载或模板实例化的条件限制,有效地控制模板的适用范围。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/18191.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android plugin如何兼容App插件和library插件

Android插件的开发&#xff0c;在网上有很多资料&#xff0c;如&#xff1a;Android Gradle 插件开发入门指南&#xff1a;https://juejin.cn/post/6887581345384497165&#xff0c;最近由于工作需要&#xff0c;开发了一个jacoco与记录用例执行顺序的插件&#xff0c;整体功能…

【Python设计模式08】原型模式

原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它通过复制现有的对象来创建新的对象&#xff0c;而不是通过实例化类来创建对象。原型模式使得对象的创建更加灵活和高效&#xff0c;特别是在创建对象的过程复杂或代价高昂时。 原型模式的…

Clickhouse Bitmap 类型操作总结—— Clickhouse 基础篇(四)

文章目录 创建 Bitmap 对象Bitmap 转换为整数数组计算总数&#xff08;去重&#xff09;值指定start, end 索引生成子 Bitmap指定 start 索引和数量限制生成子 Bitmap指定偏移量生成子 Bitmap是否包含指定元素两个 Bitmap 是否存在相同元素一个是否为另一个 Bitmap 的子集求最小…

STUMPY,一个时间序列挖掘Python分析工具

STUMPY概述: STUMPY 是一个用于时间序列数据挖掘和分析的 Python 库,它提供了一系列算法和工具,用于时间序列的相似性搜索、异常检测和模式发现.STUMPY 中的核心算法是基于 Matrix Profile 的方法,能够高效地进行时间序列分析. 安装与使用 首先安装 STUMPY:pip install stum…

P7-P9【分配器】【源文件】【OOPvs.GP】

分配器 如何分配&#xff0c;如何释放 源文件 标准库源代码文件VC布局 标准库源代码文件GCC布局 OOP(面向对象编程) VS GP(泛型编程) 这两种编程的区别&#xff1a; 面向对象编程是将数据和方法联系在一起&#xff0c;更注重对不同的对象做出不同的响应&#xff0c;更适合…

MyBatis系统学习篇 - 动态SQL

MyBatis提供了动态SQL帮助我们解决在业务过程中&#xff0c;我们根据不同的条件动态生成SQL语句&#xff0c;用来满足各种复杂的查询需求&#xff0c;包括MyBatis中常用的动态SQL标签和用法&#xff0c;这种方式在一定程度上帮助我们重复写许多SQL堆积在一起&#xff0c;下面我…

狂暴少帅短视频:成都科成博通文化传媒公司

狂暴少帅短视频&#xff1a;热血与激情的碰撞 在当下这个信息爆炸的时代&#xff0c;短视频以其独特的魅力迅速占领了人们的视线。而在众多短视频创作者中&#xff0c;一位名为“狂暴少帅”的创作者以其独特的风格和引人入胜的内容&#xff0c;赢得了广大网友的喜爱和追捧。今…

OpenHarmony应用开启Service以及完成自启动和常驻

一.背景 由于有需求实现一个后台常驻服务,这里就是来实现在鸿蒙里面如何实现后台服务并且实现自启动和常驻 二.添加服务 如下来添加服务 然后此时直接运行这个hap是报错的,如下: 此处参考: 应用中添加ServiceExtensionAbility然后安装HAP时提示“code:9568344 error: inst…

如何解决Redis缓存穿透问题?

Redis缓存穿透问题是指当客户端请求的数据在缓存中和数据库中都不存在时,缓存永远不会生效,这些请求都会直接打到数据库上,可能导致数据库压力过大。以下是几种解决Redis缓存穿透问题的方案: 缓存空值: 当查询结果为空时,也将空结果进行缓存,但设置一个较短的过期时间。…

SSH秘钥对简化github项目管理(外加Tortoise配置)

文章目录 使用SSH秘钥对简化github项目管理为什么要用密钥对&#xff1f;如何使用SSH方式克隆版本库呢&#xff1f;补充&#xff1a;使用TortoiseGit&#xff08;小乌龟&#xff09;快速访问github远程仓库&#xff01;结尾&#xff1a;喜欢的小伙伴可以点点关注赞哦 使用SSH秘…

人才测评的应用:人才选拔,岗位晋升,面试招聘测评

人才测评自诞生以来&#xff0c;就被广泛应用在各大方面&#xff0c;不仅是我们熟悉的招聘上&#xff0c;还有其他考核和晋升&#xff0c;都会需要用到人才测评。不知道怎么招聘&#xff1f;或者不懂得如何实现人才晋升&#xff1f;都可以参考人才测评&#xff0c;利用它帮我们…

怎么排查问题

1、docker启动失败&#xff0c;怎么排查问题 # 查看未启动的容器的状态 docker ps -a# 查看日志&#xff0c;分析排查 docker logs -f 容器id2、查看端口占用 已知程序名称查找占用端口 # 查看进程ID ps -ef | grep 程序名&#xff08;如port&#xff09; # 根据进程ID 查看…

AI视频教程下载:零基础学会DALL-E 、Midjourney、Microsoft Designer、Adobe Firefly

学完本课程会得到什么&#xff1a; 掌握ChatGPT、DALL-E 2、Midjourney、Microsoft Bing Chat、Microsoft Designer和Adobe Firefly&#xff0c;全面理解生成性AI及其应用 了解OpenAI及其在生成性AI领域的尖端研究 理解提示工程的重要性以及它如何帮助产生更好的输出和数据 …

Llama模型家族训练奖励模型Reward Model技术及代码实战(一)

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

2024最新升级Stable Diffusion整合包v4.6版来了,附赠SD电商实战教程

Stable Diffusion无疑是最近最火的AI绘画工具之一&#xff0c;本期设计软件库给大家带来了2024最新升级的v4.6版&#xff01;比之前推送的更加智能、快速和简单 2024全新Stable Diffusion 资料包 新版本使用更方便 独家附赠SD电商实战教程 让你快速上手 资源目录一览 01 新…

Git——pull request详细教程

当我们需要协助其他仓库完成更改时&#xff0c;往往会用到git中的Pull Request操作&#xff0c;从而方便团队的协作管理和代码持续集成。 下面是详细的教程步骤。 一. Fork目标项目 比如说我现在要fork以下Qwen-VL的项目&#xff0c;如图所示&#xff1a; 随后点击Create即可…

PENDLE会是打响LSDFI赛道的第一枪吗?以bitget钱包为例

Pendle Finance是什么? PENDLE是Pendle Finance的原生通证&#xff0c;因此&#xff0c;在介绍Pendle币之前&#xff0c;我们需要对Pendle Finance有一个简单的了解。、 Pendle是一个建立在以太坊区块链上的无需许可的去中心化金融&#xff08;DeFi&#xff09;协议&#xff…

【东山派Vision K510开发板试用笔记】WiFi配网问题

目录 概述 WiFi配网的修改 悬而未决的问题 概述 最近试用了百问网提供的东山派Vision开发板&#xff0c;DongshanPI-Vision开发板是百问网针对AI应用开发设计出来的一个RSIC-V架构的AI开发板&#xff0c;主要用于学习使用嘉楠的K510芯片进行Linux项目开发和嵌入式AI应用开发…

使用PyInstaller打包一个包含多个文件的Python项目

使用PyInstaller打包一个包含多个文件的Python项目涉及以下几个步骤&#xff1a; 安装PyInstaller&#xff1a; 如果你还没有安装PyInstaller&#xff0c;可以通过pip安装&#xff1a; pip install pyinstaller编写.spec文件: PyInstaller允许你创建一个.spec文件来指定打包的详…

来自工业界的知识库 RAG 服务(二),RagFlow 源码全流程深度解析

背景介绍 前面介绍过 有道 QAnything 源码解析&#xff0c;通过深入了解工业界的知识库 RAG 服务&#xff0c;得到了不少调优 RAG 服务的新想法。 因此本次趁热打铁&#xff0c;额外花费一点时间&#xff0c;深入研究了另一个火热的开源 RAG 服务 RagFlow 的完整实现流程&…