将枚举值与 SFINAE 结合使用

2024-04-28

我已经熟悉 SFINAE 以及如何使用它来根据传递的类型启用特定模板(通过使用 std::enable_if)。不过,我最近开始从事一个项目,我想在该项目中执行以下操作:在使用 SFINAE 时根据提供的枚举值创建一个类专业化。现在,我知道考虑到我之前已经这样做过(像这样),可以根据枚举值进行专业化:

enum Specifier
{
   One,
   Two,
   Three
}

template <Specifier>
class Foo
{
public:
   void Bar();
}

template<>
void Foo<Specifier::One>::Bar()
{
}

但是现在我想使用 SFINAE 来使用特定的专业化Bar()对于多个枚举值。像这样的事情:

template <Specifier Type>
class Foo
{
public:
   template <typename std::enable_if<Type == Specifier::Two || Type == Specifier::One, void>::type> 
   void Bar();

   template <typename std::enable_if<Type == Specifier::Three, void>::type> 
   void Bar();
}

知道这是否可能吗?如果可以,我将如何去做?


C++17:constexpr if

从 C++17 及更高版本开始,您可以使用单个成员函数重载(而不是通过 SFINAE 存在或不存在的多个重载),其主体利用 constexpr,如果:

#include <iostream>

enum class Specifier { One, Two, Three };

template <Specifier S> class Foo {
public:
  static constexpr int bar() {
    if constexpr ((S == Specifier::One) || (S == Specifier::Two)) {
      return 12;
    } else if constexpr (S == Specifier::Three) {
      return 3;
    }
  }
};

int main() {
  std::cout << Foo<Specifier::One>::bar() << "\n" // 12
            << Foo<Specifier::Two>::bar() << "\n" // 12
            << Foo<Specifier::Three>::bar();      // 3
}

C++11:SFINAE 和std::enable_if(_t) (C++14)

您同样可以使用 SFINAE,但要求您的非模板成员函数需要成为带有虚拟模板参数的成员函数模板,因为 SFINAE 需要应用于附属名称在每个函数声明中,类模板(类型或非类型)参数自然不是函数声明中的依赖名称非模板会员功能:

template <Specifier S> class Foo {
public:
  template <Specifier S_ = S,
            std::enable_if_t<(S_ == Specifier::One) || (S_ == Specifier::Two)>
                * = nullptr>
  static constexpr int bar() {
    return 12;
  }

  template <Specifier S_ = S,
            std::enable_if_t<(S_ == Specifier::Three)> * = nullptr>
  static constexpr int bar() {
    return 3;
  }
};

请注意,上面的示例使用了助手别名模板std::enable_if_t这是在 C++14 中引入的。如果您使用的是 C++11,则需要使用typename std::enable_if<..>::type反而。

此外请注意,由于我们必须模板化成员函数,滥用者可能会选择覆盖(虚拟)非类型模板参数的默认模板参数S_:

Foo<Specifier::One>::bar<Specifier::Three>();  // 3

所以我们可能想添加一个额外的 AND 条件std::enable_if_t每个重载的谓词,即(S_ == S) && (... predicate as above)。正如我们将在接下来的部分中看到的,这在 C++20 中不再是问题,因为我们可以避免仅为了应用 SFINAE 将非模板成员函数放入模板。

使用专业化而不是重载的替代方案

正如我也展示过的以下答案 https://stackoverflow.com/a/64912160/4573247对于这个问题的后续问题,您还可以在专业化的模板参数列表中应用 SFINAE(对于部分专业化的类模板):

template <Specifier, typename = void> struct Foo {
  static constexpr int bar() { return 1; }  // default
};

template <Specifier S>
struct Foo<S,
           std::enable_if_t<(S == Specifier::One) || (S == Specifier::Two)>> {
  static constexpr int bar() { return 12; }
};

C++20:类模板的非模板成员函数可以使用要求子句:s

从 C++20 开始,您可以使用尾随来重载和约束类模板的非模板成员函数要求子句每个重载具有互斥约束:

template <Specifier S> class Foo {
public:
  static constexpr int bar() requires((S == Specifier::One) ||
                                      (S == Specifier::Two)) {
    return 12;
  }

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

将枚举值与 SFINAE 结合使用 的相关文章

  • 将字节数组转换为托管结构

    更新 这个问题的答案帮助我编写了开源项目GitHub 上的 AlicanC 现代战争 2 工具 https github com AlicanC AlicanC s Modern Warfare 2 Tool 你可以看到我是如何阅读这些数据
  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • 在 C++ 中将成对向量转换为两个独立向量的最快方法

    假设我有一个vector of pair
  • SFINAE 如何使用省略号?

    过去 当使用 SFINAE 选择构造函数重载时 我通常使用以下内容 template
  • 如何生成 appsettings..json 文件?

    我有一个 ASP NET Core 2 WebAPI 它将部署在以下环境中 INT QA STAGE 生产环境 基于上述 我需要有appsettings
  • HttpWebRequest vs Webclient(特殊场景)

    我知道这个问题之前已经回答过thread https stackoverflow com questions 1694388 webclient vs httpwebrequest httpwebresponse 但我似乎找不到详细信息 在
  • 无法解析远程名称 - webclient

    我面临这个错误 The remote name could not be resolved russgates85 001 site1 smarterasp net 当我请求使用 Web 客户端读取 html 内容时 出现错误 下面是我的代
  • 从成员函数指针类型生成函子

    我正在尝试简化 通过make fn 预处理参数的函子的生成 通过wrap 对于 arity 的成员函数n 生成函子基本上可以工作 但到目前为止只能通过显式指定成员函数的参数类型来实现 现在我想从它处理的成员函数类型生成正确的函子 struc
  • libxml2 xmlChar * 到 std::wstring

    libxml2似乎将所有字符串存储在 UTF 8 中 如xmlChar xmlChar This is a basic byte in an UTF 8 encoded string It s unsigned allowing to pi
  • 分配器感知容器和propagate_on_container_swap

    The std allocator traits模板定义了一些常量 例如propagate on container copy move assign让其他容器知道它们是否应该在复制或移动操作期间复制第二个容器的分配器 我们还有propag
  • C++11 动态线程池

    最近 我一直在尝试寻找一个用于线程并发任务的库 理想情况下 是一个在线程上调用函数的简单接口 任何时候都有 n 个线程 有些线程比其他线程完成得更快 并且到达的时间不同 首先我尝试了 Rx 它在 C 中非常棒 我还研究了 Blocks 和
  • C# 中的常量和只读? [复制]

    这个问题在这里已经有答案了 可能的重复 const 和 readonly 之间有什么区别 https stackoverflow com questions 55984 what is the difference between cons
  • 二叉树中的 BFS

    我正在尝试编写二叉树中广度优先搜索的代码 我已将所有数据存储在队列中 但我不知道如何访问所有节点并消耗它们的所有子节点 这是我的 C 代码 void breadthFirstSearch btree bt queue q if bt NUL
  • 从 R 到 C 处理列表并访问它

    我想使用从 R 获得的 C 列表 我意识到这个问题与此非常相似 使用 call 在 R 和 C 之间传递数据帧 https stackoverflow com questions 6658168 passing a data frame f
  • .NET 客户端中 Google 表格中的条件格式请求

    我知道如何在 Google Sheets API 中对值和其他格式进行批量电子表格更新请求 但条件格式似乎有所不同 我已正确设置请求 AddConditionalFormatRuleRequest formatRequest new Add
  • 使用 mingw32 在 Windows 上构建 glew 时“DllMainCRTStartup@12”的多个定义

    我关注了这个主题 使用 mingw 使建筑物在 Windows 上闪闪发光 https stackoverflow com questions 6005076 building glew on windows with mingw 6005
  • 使用 iTextSharp 5.3.3 和 USB 令牌签署 PDF

    我是 iTextSharp 和 StackOverFlow 的新手 我正在尝试使用外部 USB 令牌在 C 中签署 PDF 我尝试使用从互联网上挖掘的以下代码 Org BouncyCastle X509 X509CertificatePar
  • C 中带有指针的结构的内存开销[重复]

    这个问题在这里已经有答案了 我意识到当我的结构包含指针时 它们会产生内存开销 这里有一个例子 typedef struct int num1 int num2 myStruct1 typedef struct int p int num2
  • 受限 AppDomain 中的代码访问安全异常

    Goal 我需要在权限非常有限的 AppDomain 中运行一些代码 它不应该访问任何花哨或不安全的内容 except对于我在其他地方定义的一些辅助方法 我做了什么 我正在创建一个具有所需基本权限的沙箱 AppDomain 并创建一个运行代
  • OSError: [WinError 193] %1 不是有效的 Win32 应用程序,同时使用 CTypes 在 python 中读取自定义 DLL

    我正在尝试编写用 python 封装 C 库的代码 我计划使用 CTypes 来完成此操作 并使用 Visual Studio 来编译我的 DLL 我从一个简单的函数开始 在 Visual Studio 内的标头中添加了以下内容 然后将其构

随机推荐

  • Emacs lisp:将字符翻译为标准 ASCII 转录

    我正在尝试编写一个函数 将包含 unicode 字符的字符串转换为某种默认的 ASCII 转录 理想情况下 我想要例如 ngstr m成为Angstroem或者 如果不可能的话 Angstrom 同样地 应该成为a x c 或类似的 Ema
  • 如何使用我自己的声明文件解决“无法找到模块的声明文件”错误?

    我有一个测试项目 正在其中测试类型定义文件 该项目有一个文件名为index ts看起来像这样 import i18nFu require gettext js The 获取文本 js包是使用 Node js 安装的 如下所示 npm ins
  • iOS 7 中的后台任务间隔时间

    我在 appdidEnterBackground 中有以下代码 我看到在 IOS 6 中我看到后台时间段约为 10 分钟 而 IOS 7 中的相同代码打印 2 分钟 这是代码 void applicationDidEnterBackgrou
  • 当有太多需要滚动的项目时,Windows 窗体列表框会溢出

    我正在构建一个基于后缀树的索引器应用程序 它使我能够非常快地索引整个文档并搜索字符串 子字符串等 我正在做的是在文本框中输入一个字符串 按下按钮 然后运行一个函数来查询后缀树并将所有出现的字符串的位置添加到列表框中 所以列表框里面有很多整数
  • 用于从 PHP 更新实时
  • 的 jQuery 插件
  • 有没有任何 jQuery 插件可以创建类似实时 feed 的东西推特主页 http www twitter com 使用 PHP 它从 MySQL 数据库获取数据 PHP 文件必须如何 Thanks 您确实不需要为此使用插件 您可以使用 j
  • MS Access 2007 中 NVL 功能的替代方法是什么

    我在 MS Access 中编写了一个 SQL 查询 select NVL count re rule status 0 from validation result re validation rules ru where re cycl
  • 实体框架 LINQ To Entities 生成奇怪的慢速 SQLWhere 子句

    我需要理解这一点 EF5 0 和 EF6 在 TSQL 代码生成方面存在很大差异 在我的代码中 这是我的 LINQ 语句 var qry2 context viw overview 1 Where i gt i article EAN17
  • 设置div内的div滚动,而父级不滚动

    我有一个容器 div 其中包含许多子 div 我的容器中的 div 之一包含评论 我不想将整个 div 设置为滚动 而是希望所有内容都保持在原位 只留下评论 div 滚动 我尝试将父级溢出设置为隐藏 将注释 div 设置为滚动 滚动条实际上
  • 为什么旋转图像时会出现黑色边框? PHP GD

    此代码使用 GD 生成两张图像并旋转其中一张 当我旋转图像时 黑色边框开始出现 有人知道如何解决这个问题吗
  • 如何更改传单弹出窗口的背景颜色?

    我正在使用 Leafletjs 创建地图 我想将弹出窗口 当前显示图像和链接 的背景颜色从白色更改为其他颜色 看起来基本的背景颜色 CSS 语法并不能解决这个问题 有什么建议吗 谢谢 斯科特 调用 leaflet css 后 您可以包含
  • std::array<> 的初始化

    考虑以下代码 include
  • ssh:无法确定主机“主机名”的真实性

    当我 ssh 到一台机器时 有时我会收到此错误警告 并提示说 是 或 否 当从自动 ssh 到其他机器的脚本运行时 这会导致一些问题 警告信息 The authenticity of host
  • 如何根据 MuMIn model.avg() 摘要进行绘图

    有没有一种方法可以直接绘制 MuMIn model avg 对于具有置信带的不同变量的模型平均摘要输出 以前我一直使用 ggplot 和 ggpredict 来绘制实际模型中的项 但我一直无法找到一种方法来绘制平均模型的结果 显然 我可以手
  • iPhone:如何删除/清除蓝牙 4.0 数据

    我有一些大麻烦 https stackoverflow com questions 11557500 corebluetooth central manager callback diddiscoverperipheral twice co
  • 发生错误时如何停止powershell脚本?

    我有一个 主 powershell 脚本 它执行多个在虚拟机上安装应用程序的脚本 我正在尝试在主脚本上实现错误控制 意思是 如果安装应用程序的脚本之一失败 则不会执行其余脚本 这是我的主要脚本 try powershell exe Exec
  • gets() 和 put() 未在 dev C++ 范围内声明

    这是我的书店的简单代码 代码没有任何问题 我正在使用 DevC 运行代码 编译后给出一个错误 指出 gets 未在此范围内声明 并且 put 也出现相同的错误 请帮我 include
  • 无法在 CUDA 中执行设备内核

    我正在尝试在全局内核中调用设备内核 我的全局内核是矩阵乘法 我的设备内核正在查找乘积矩阵每列中的最大值和索引 以下是代码 device void MaxFunction float Pd float max int x threadIdx
  • render* 函数不会显示在闪亮模块内的 modalDialog 中

    我一直在使用showModal modalDialog 在我的闪亮应用程序中将图表显示为弹出窗口 但是当我将它们放入闪亮模块中时 这些图不会呈现 简短重现如下 非模块触发模态显示图形 模块触发模态显示为空白 有人有主意吗 模态框本身可以正确
  • Haskell / SmallCheck:如何控制“Depth”参数?

    我有一个简单的数据结构可以在smallcheck 中测试 LANGUAGE FlexibleInstances MultiParamTypeClasses LANGUAGE DeriveGeneric import Test Tasty i
  • 将枚举值与 SFINAE 结合使用

    我已经熟悉 SFINAE 以及如何使用它来根据传递的类型启用特定模板 通过使用 std enable if 不过 我最近开始从事一个项目 我想在该项目中执行以下操作 在使用 SFINAE 时根据提供的枚举值创建一个类专业化 现在 我知道考虑