Eric Niebler 的 std::is_function 实现是如何工作的?

2024-03-11

上周埃里克·尼伯勒tweeted https://twitter.com/ericniebler/status/852192542653329408一个非常紧凑的实现std::is_function http://en.cppreference.com/w/cpp/types/is_function特质类:

#include <type_traits>

template<int I> struct priority_tag : priority_tag<I - 1> {};
template<> struct priority_tag<0> {};

// Function types here:
template<typename T>
char(&is_function_impl_(priority_tag<0>))[1];

// Array types here:
template<typename T, typename = decltype((*(T*)0)[0])>
char(&is_function_impl_(priority_tag<1>))[2];

// Anything that can be returned from a function here (including
// void and reference types):
template<typename T, typename = T(*)()>
char(&is_function_impl_(priority_tag<2>))[3];

// Classes and unions (including abstract types) here:
template<typename T, typename = int T::*>
char(&is_function_impl_(priority_tag<3>))[4];

template <typename T>
struct is_function
    : std::integral_constant<bool, sizeof(is_function_impl_<T>(priority_tag<3>{})) == 1>
{};

但它是如何运作的呢?


总体思路

而不是列出所有有效的函数类型,例如cpprefereence.com 上的示例实现 http://en.cppreference.com/w/cpp/types/is_function,此实现列出了所有类型not函数,然后只解析为true如果这些都不匹配。

非函数类型列表包括(从下到上):

  • 类和联合(包括抽象类型)
  • 可以从函数返回的任何内容(包括void和参考类型)
  • 数组类型

与任何这些非函数类型都不匹配的类型是函数类型。注意std::is_function显式地将可调用类型(如 lambda 或带有函数调用运算符的类)视为not是函数。

is_function_impl_

我们提供了一种超载is_function_impl每个可能的非函数类型的函数。函数声明可能有点难以解析,所以让我们以以下示例来分解它:阶级和工会 case:

template<typename T, typename = int T::*>
char(&is_function_impl_(priority_tag<3>))[4];

这一行声明了一个函数模板is_function_impl_需要一个类型参数priority_tag<3>并返回对 4 数组的引用chars。正如 C 语言自古以来的惯例,声明语法因数组类型的存在而变得极其复杂。

该函数模板采用两个模板参数。第一个只是无约束T,但第二个是指向成员的指针T类型的int. The int这里的部分并不重要,即。这甚至适用于T没有任何类型的成员int。但它的作用是会导致语法错误T不属于类或联合类型。对于那些其他类型,尝试实例化函数模板将导致替换失败。

类似的技巧也用于priority_tag<2> and priority_tag<1>重载,它使用第二个模板参数来形成仅编译的表达式Ts 分别是有效的函数返回类型或数组类型。只有priority_tag<0>重载没有这样的约束第二个模板参数,因此可以用任何实例化T.

总而言之,我们声明了四种不同的重载is_function_impl_,它们的输入参数和返回类型有所不同。他们每个人都采取不同的priority_tag类型作为参数并返回对不同唯一大小的 char 数组的引用。

标签调度在is_function

现在,在实例化时is_function,它实例化is_function_impl with T。请注意,由于我们为此函数提供了四种不同的重载,因此必须在此处进行重载解析。由于所有这些重载都是函数模板,这意味着SFINAE http://en.cppreference.com/w/cpp/language/sfinae有机会介入。

因此,对于函数(并且仅是函数),所有重载都会失败,除了最常见的重载priority_tag<0>。那么,如果实例化是最通用的重载,为什么实例化并不总是解决该重载呢?因为我们重载函数的输入参数。

注意priority_tag是这样构造的priority_tag<N+1>公开继承自priority_tag<N>。现在,自从is_function_impl在这里被调用priority_tag<3>,该过载是更好的匹配比其他重载决议,所以它会首先尝试。仅当由于替换错误而失败时,才会尝试下一个最佳匹配,即priority_tag<2>超载。我们继续以这种方式,直到找到可以实例化的重载或者达到priority_tag<0>,它不受限制并且始终有效。由于所有非函数类型都被较高的 prio 重载覆盖,因此这种情况只能发生在函数类型上。

评估结果

我们现在检查调用返回的类型的大小is_function_impl_来评估结果。请记住,每个重载都会返回对不同大小的 char 数组的引用。因此我们可以使用sizeof检查选择了哪个重载并仅将结果设置为true如果我们到达priority_tag<0>超载。

已知错误

约翰内斯·绍布发现一个错误 https://stackoverflow.com/questions/43470741/how-does-eric-nieblers-implementation-of-stdis-function-work#comment74188378_43470962在实施中。不完整类类型的数组将被错误地分类为函数。这是因为当前数组类型的检测机制不适用于不完整的类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Eric Niebler 的 std::is_function 实现是如何工作的? 的相关文章

  • Qt-Qlist 检查包含自定义类

    有没有办法覆盖加载自定义类的 Qt QList 的比较机制 即在 java 中你只需要重写一个比较方法 我有一个带有我的自定义类模型的 QList QList
  • 当我使用“control-c”关闭发送对等方的套接字时,为什么接收对等方的套接字不断接收“”

    我是套接字编程的新手 我知道使用 control c 关闭套接字是一个坏习惯 但是为什么在我使用 control c 关闭发送进程后 接收方上的套接字不断接收 在 control c 退出进程后 发送方的套接字不应该关闭吗 谢谢 我知道使用
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • 获取没有非标准端口的原始 url (C#)

    第一个问题 环境 MVC C AppHarbor Problem 我正在调用 openid 提供商 并根据域生成绝对回调 url 在我的本地机器上 如果我点击的话 效果很好http localhost 12345 login Request
  • 如何将图像和 POST 数据上传到 Azure 移动服务 ApiController 终结点?

    我正在尝试上传图片and POST表单数据 尽管理想情况下我希望它是json 到我的端点Azure 移动服务应用 我有ApiController method HttpPost Route api upload databaseId sea
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • 指针减法混乱

    当我们从另一个指针中减去一个指针时 差值不等于它们相距多少字节 而是等于它们相距多少个整数 如果指向整数 为什么这样 这个想法是你指向内存块 06 07 08 09 10 11 mem 18 24 17 53 7 14 data 如果你有i
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 在 ASP.NET Core 3.1 中使用包含“System.Web.HttpContext”的旧项目

    我们有一些用 Net Framework编写的遗留项目 应该由由ASP NET Core3 1编写的API项目使用 问题是这些遗留项目正在使用 System Web HttpContext 您知道它不再存在于 net core 中 现在我们
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 如何将单个 char 转换为 int [重复]

    这个问题在这里已经有答案了 我有一串数字 例如 123456789 我需要提取它们中的每一个以在计算中使用它们 我当然可以通过索引访问每个字符 但是如何将其转换为 int 我研究过 atoi 但它需要一个字符串作为参数 因此 我必须将每个字
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • 在 Dynamics CRM 插件中访问电子邮件发件人地址

    我正在编写一个 Dynamics CRM 2011 插件 该插件挂钩到电子邮件实体的更新后事件 阶段 40 pipeline http msdn microsoft com en us library gg327941 aspx 并且在此阶
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob

随机推荐

  • Android浮动操作按钮隐藏在底部导航栏后面

    Android 编程新手 现在正在苦苦挣扎 我正在使用 android studio 的默认 导航抽屉活动 最重要的是 我添加了一个底部栏https github com roughike BottomBar 但是 添加后我的 FAB 已隐
  • 自动展开并给予 SearchView 焦点

    我正在开发一个应用程序 用户在其中按下 搜索 图标ActionBar and a SearchView在屏幕顶部可见 我的问题是SearchView既不处于焦点也不展开 因此用户必须按搜索按钮Searchview使其展开并带出键盘 这应该如
  • __cplusplus 指令在各种编译器中是如何定义的?

    我的编译器将其扩展为 199711L 这意味着什么 我读到 cplusplus gt 199711L 表示 C 11 这个宏可能有哪些扩展 它意味着什么 199711L 代表年 1997 月 11 即 1997 年 11 月 委员会批准该标
  • 我的 AWS 策略有什么问题?

    我正在尝试向程序化 IAM 用户授予对单个存储桶的访问权限 我设置了以下策略并将其附加到用户 Version 2012 10 17 Statement Effect Allow Action s3 ListBucket Resource a
  • Android - Google Maps api v2 - 禁用缩放控制

    如何禁用 Google 地图上的 放大 按钮 我尝试寻找类似的命令 map getUiSettings setZoomControlsEnabled true SOMETHING但什么都不存在 我想把创建自己的缩放按钮作为最后的手段 UPD
  • AngularJS - 从自定义过滤器中的控制器访问 $scope

    我有一个controller与各种 scopes 我需要在自定义过滤器中访问这些 scopes 之一 app controller AppController function scope scope var1 Some data1 sco
  • 为 numpy 安装 lapack

    运行 Ubuntu 11 10 python2 7 从源代码构建 numpy 并安装它 但是当我去安装它时 我得到 ImportError usr lib liblapack so 3gf undefined symbol ATL chem
  • 如何修复 Flash 安全错误 #2048

    我在 flash 2048 中遇到错误 我能找到的所有内容都表明这是一项安全预防措施 因为文件不在同一域中 我们有一个在 Rackspace 云服务器上运行的网站 现在正尝试使用云文件 CDN 来加速我们在网站上使用的产品轮换工具 您可以使
  • 如何验证用作反向代理的 Squid 是否正常工作?

    我们希望减少其中一台 Web 服务器的负载 并且正在使用配置为反向代理的鱿鱼运行一些测试 配置在下面的备注中 http port 80 accel defaultsite original server com cache peer ori
  • 用于查找名称以给定值开头的属性的 XPath

    使用这个 xml div a div div b div div c div div d div div f div div g div 我们只想找到 div a div div b div div c div 哪些节点具有属性 其中该属性
  • 为什么使用粘贴创建的文件名中有一个空格?

    我试图使用 R 编写一个文件 为了区分每个文件 我尝试每次在函数中添加不同的后缀 例如 counts lt function counts file name lt substr counts file 1 5 file lt paste
  • 在快速分配任务时

    将 Objective C 代码转换为 Swift 的正确方法是什么 while size inputdata readWithByteArray buf 1 我需要类似的 从这里 https stackoverflow com a 256
  • JAR 中的 Spring Boot + Elastic Beanstalk .ebextensions

    我有一个非常标准的 Spring Boot 应用程序 带有application properties属性文件位于标准 src main resources文件夹 我将其作为 fat JAR 部署在 AWS Elastic Beanstal
  • 如何在 Matlab 中绘制 3D 平面?

    我想使用从 3 个点计算得出的向量绘制一个平面 其中 pointA 0 0 0 pointB 10 20 10 pointC 10 20 10 plane1 cross pointA pointB pointA pointC 如何以 3D
  • Linux进程间共享内存

    我有使用多个进程的服务器 fork 有大量数据可以由一个进程创建 并且应该在其他进程之间共享 因此 我使用 shm open mmap 创建共享内存并将其映射到虚拟内存 struct SharedData const char name i
  • DataGridView 工具提示文本未显示

    我有数据绑定DataGridView在桌面应用程序中 其中的列有其ToolTipText属性集 但当我将鼠标悬停在网格视图 单元格或单元格标题 上时 没有显示工具提示 The ShowCellToolTips网格视图的属性是true 并且我
  • 如何在 C++ 中读取文件并获取单词

    我很好奇如何从没有固定结构 例如注释或小报告 的文本文件中逐字读取输入 例如 文本的结构可能如下 1992 年 6 月 5 日今天是个好日子 虫子已经转变 战斗胜利了 我在想也许可以使用 getline 获取该行 然后看看是否可以通过空格将
  • Flask 给出内部服务器错误而不是渲染 404

    在我的 Flask 应用程序中 我设置了一个 404 处理程序 如下所示 app errorhandler 404 def page not found e return render template 404 html 404 但是 当用
  • std::unique_ptr 用法

    std unique ptr
  • Eric Niebler 的 std::is_function 实现是如何工作的?

    上周埃里克 尼伯勒tweeted https twitter com ericniebler status 852192542653329408一个非常紧凑的实现std is function http en cppreference co