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 实现是如何工作的? 的相关文章

  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • 在实体框架拦截器中向 DbScanExpression 添加内部联接

    我正在尝试使用实体框架 CommandTree 拦截器通过 DbContext 向每个查询添加过滤器 为了简单起见 我有两个表 一个称为 User 有两列 UserId 和 EmailAddress 另一个称为 TenantUser 有两列
  • 模板中的 bson.ObjectId

    我有一个具有 bson ObjectId 类型的结构 例如如下所示 type Test struct Id bson ObjectId Name string Foo string 我想在 html 模板中呈现它 Name Food a h
  • ASP.NET Web API 客户端 ProgressMessageHandler Post 任务卡在 WinForm 应用程序中

    我在用着HttpClient and ProgressMessageHandler来自MS ASP NET Web API 客户端库 http nuget org packages Microsoft AspNet WebApi Clien
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • 找不到 assimp-vc140-mt.dll ASSIMP

    我已经从以下位置下载了 Assimp 项目http assimp sourceforge net main downloads html http assimp sourceforge net main downloads html Ass
  • 时间:2019-03-17 标签:c#ThreadSafeDeepCopy

    我一直在阅读很多其他问题以及大量谷歌搜索 但我一直无法找到明确的解决方案 根据我读过的一些最佳实践 类的静态方法应该创建线程安全的 并且实例成员应该将线程安全留给消费者 我想为该类实现深度复制方法 该类本身还有其他引用类型成员 有没有什么方
  • vs2008 c#:Facebook.rest.api如何使用它来获取好友列表?

    如何在此基础上取得进一步的进步 获取好友列表的下一步是什么 string APIKey ConfigurationManager AppSettings API Key string APISecret ConfigurationManag
  • 如何从文本文件读取整数到数组

    这就是我想做的 我对此有些不满 但我希望你能容忍我 这对我来说是一个非常新的概念 1 在我的程序中 我希望创建一个包含 50 个整数的数组来保存来自文件的数据 我的程序必须获取用户的文档文件夹的路径 2 文件的名称为 grades txt
  • C# 中的 strstr() 等效项

    我有两个byte 我想找到第二个的第一次出现byte 在第一个byte 或其中的一个范围 我不想使用字符串来提高效率 翻译第一个byte to a string会效率低下 基本上我相信就是这样strstr 在 C 中做 最好的方法是什么 这
  • IEnumerable.Except 不起作用,那么我该怎么办?

    我有一个 linq to sql 数据库 非常简单 我们有 3 个表 项目和用户 有一个名为 User Projects 的连接表将它们连接在一起 我已经有了一个获得的工作方法IEnumberable
  • cout 和字符串连接

    我刚刚复习了我的 C 我尝试这样做 include
  • 了解使用 Windows 本机 WPF 客户端进行 ADFS 登录

    我已经阅读了大量有关 ADFS 与 NodeJS Angular 或其他前端 Web 框架集成以及一般流程如何工作的文献 并通过 Auth0 Angular 起始代码构建了概念证明 但我不明白如何这可以与本机 WPF Windows 应用程
  • 跨多个域的 ASP.NET 会话

    是否有合适的 NET 解决方案来在多个域上提供持久服务器会话 即 如果该网站的用户在 www site1 com 下登录 他们也将在 www site2 com 下登录 安全是我们正在开发的程序的一个问题 Thanks 它是否需要在会话中
  • 使用taskkill停止Windows服务

    我需要帮助来使用 C 终止 Windows 服务 现在要终止该服务 请使用以下选项 从命令 sc queryex ServiceName 发现后PID服务的 taskkill pid 1234 exemple f 为了便于阅读 但如果您明白
  • 矩阵到数组 C#

    这将是转换方阵的最有效方法 例如 1 2 3 4 5 6 7 8 9 into 1 2 3 4 5 6 7 8 9 in c 我在做 int array2D new int 1 2 3 4 5 6 7 8 9 int array1D new
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map
  • ASP.NET Core MVC 视图组件搜索路径

    在此处的文档中 https learn microsoft com en us aspnet core mvc views view components view aspnetcore 2 2 https learn microsoft
  • xsi:type 属性搞乱了 C# XML 反序列化

    我使用 XSD exe 根据 XML 架构 xsd 文件 自动生成 C 对象 我正在反序列化 OpenCover 输出 但其中一个部分类未正确生成 这是导致异常的行
  • Java 和/C++ 在多线程方面的差异

    我读过一些提示 多线程实现很大程度上取决于您正在使用的目标操作系统 操作系统最终提供了多线程能力 比如Linux有POSIX标准实现 而windows32有另一种方式 但我想知道编程语言水平的主要不同 C似乎为同步提供了更多选择 例如互斥锁

随机推荐

  • 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