用模板元编程的方式判断一个结构体是否含有某成员函数

news/2024/11/16 7:30:28/

最近在看kdtree的东西找到一个只包含头文件的实现版,看到里面有这样一段代码一脸懵


template <typename T, typename = int> struct has_resize : std::false_type {};

查了一下才知道这个语句是一个用于进行模板元编程的定义。它定义了一个模板结构体 has_resize,该结构体用于判断类型 T 是否拥有 resize 成员函数。

让我们逐步解释这个语句:

template <typename T, typename=int> struct has_resize : std::false_type {};
  • template <typename T, typename=int>:这代表着这是一个模板结构体,并接受两个模板参数。第一个参数 T 是待检查的类型,第二个参数 int 是一个默认参数。
  • struct has_resize : std::false_type {}:这定义了一个结构体 has_resize,并继承自 std::false_type 类。std::false_type 是一个标准库中的结构体,用于表示布尔值 false

这段代码的作用是定义了 has_resize 结构体,并将其默认初始化为 std::false_type,意味着默认情况下假设待检查的类型 T 不具有 resize 成员函数。

此时,我们可以使用特化(specialization)来对具体的类型进行判断。如果某个特定类型 T 拥有 resize 成员函数,那么可以创建一个非模板的 has_resize<T> 的部分特化版本,将其继承自 std::true_type 类,从而改变默认的 std::false_typestd::true_type

template <typename T> struct has_resize<T, decltype(std::declval<T>().resize(0), 0)> : std::true_type {};

这个部分特化的定义使用了 SFINAE(Substitution Failure Is Not An Error)机制来根据 T 的属性进行匹配。如果 T 类型在调用表达式 std::declval<T>().resize(0) 时能够通过编译,那么这个部分特化将生效,继承自 std::true_type,表示类型 T 确实具有 resize 成员函数。

通过结合这两部分定义,我们可以在模板元编程中使用 has_resize<T>::value 来判断某个类型 T 是否支持 resize 成员函数。如果 has_resize<T>::valuetrue,则表示类型 T 支持 resize 成员函数;如果为 false,则表示不支持。

例如:

#include <iostream>
#include <type_traits>template <typename T, typename=int> struct has_resize : std::false_type {};template <typename T>
struct has_resize<T, decltype(std::declval<T>().resize(0), 0)> : std::true_type {};class Container {
public:void resize(int size) {std::cout << "Resizing container to size: " << size << std::endl; }
};class NoResizeContainer {// 没有 resize 成员函数
};int main() {std::cout << std::boolalpha;std::cout << has_resize<Container>::value << std::endl;  // 输出 truestd::cout << has_resize<NoResizeContainer>::value << std::endl;  // 输出 falsereturn 0;
}

在上述示例中,has_resize<Container>::value 的值为 true,表示 Container 类型具有 resize 成员函数。而 has_resize<NoResizeContainer>::value 的值为 false,表示 NoResizeContainer 类型不具有 resize 成员函数。

这种技术可以用于编写更加泛化和灵活的代码,根据类型的特性来进行条件判断和分发。


http://www.ppmy.cn/news/1022701.html

相关文章

Kubernetes pod调度约束[亲和性 污点] 生命阶段 排障手段

调度约束 Kubernetes 是通过 List-Watch 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件&#xff0c;向 APIServer 发送命令&#xff0c;在 Node 节点上面建立 Pod 和 Container。 APIServer…

【JUC】复习指南

JUC复习指南&#xff1a; JUC有哪些知识点&#xff1f; 什么是Juc Lock接口 线程间通信 集合的线程安全问题 多线程锁 Callable接口 JUC三大辅助类 CountDownLatch CyclicBarrier Semaphore 读写锁 ReetrantReadWriteLOck 阻塞队列 ThreadPool线程池 Fork/join Com…

element中select下拉框如何实现宽度自适应

简单暴力&#xff1a; element 和 elementPlus 都可以直接在el-select上添加 style"width: 100%" 解决 <el-select style"width: 100%" v-model"cats" multiple filterable placeholder"请选择分类"> . . . </el-select&…

C语言错题之 10

前言 不知不觉这个专栏都更到第十篇文章了&#xff0c;真快啊&#xff0c;继续加油。 今天给大家带来的是六道选择题&#xff0c;明天会出五道我最近在做题的时候遇到的有意思的编程题。 话不多说&#xff0c;直接看今天的题。 1. 题干&#xff1a; 下面代码的运行结果是&a…

“可一学院”区块链学习平台正式启动,助力BSV技术普及与传播

2023年8月8日&#xff0c;上海可一澈科技有限公司&#xff08;以下简称“可一科技”&#xff09; 正式发布区块链学习平台“可一学院”。“可一学院” 立足于BSV区块链技术本源&#xff0c;汇集了多层次的专业课程和学习资源&#xff0c;致力于打造一个适合各类人群使用的一站式…

bye 我的博客网站

Bye&#x1f64b;&#x1f64b;&#x1f64b;&#xff0c;我的博客网站。在我的服务器上运行了9个月之久的博客网站要和大家Bye了。 背景 可能很多人不知道我的这个博客网站的存在&#xff0c;好吧&#xff0c;最后一次展示它了&#xff0c;博客网站地址在这里&#xff0c;它…

QT的信号槽的四种写法和五种链接方式

目录 四种信号槽写法&#xff1a; 五种连接方式&#xff1a; 实例&#xff1a; 常见错误及改正&#xff1a; 错误1: 未连接信号与槽 错误2: 信号和槽参数不匹配 错误3: 未使用Q_OBJECT宏 错误4: 跨线程连接未处理 在Qt中&#xff0c;信号&#xff08;Signal&#xff09…

IDEA每次启动indexing解决办法

每次启动indexing很浪费时间。 解决办法 setting中搜索index 设置如下&#xff1a; 这样设置以后&#xff0c;启动速度明显快多了。 参考 https://blog.csdn.net/qq_45162113/article/details/121128721