如何根据条件和参数数量启用结构体?

2023-12-05

我想创建一个元函数,如果向其传递超过 1 个参数,则返回特定类型;如果仅向其传递一个参数,则返回基于条件的另一种类型。该条件是任意的,因此需要enable_if或类似的东西,但对于这个例子,我只是将其作为类型比较。让我们将其简化为以下内容

  1. 如果传递单个参数并且该参数是int, 返回bool
  2. 如果传递单个参数并且该参数是double, 返回int
  3. 如果传递了超过 1 个参数,则返回double

为了实现这一目标,我尝试执行以下操作:

#include <type_traits>

template <typename Enable, typename...Args>                                 
struct Get;                                                     

// multiple arguments; return double regardless of the condition
template <typename FirstArg, typename... OtherArgs>                       
struct Get<typename std::enable_if<true>::type, FirstArg, OtherArgs...>
{                                                                               
    using type = double;
};

// single int; return bool
template <typename Arg>                       
struct Get<typename std::enable_if<std::is_same<Arg, int>::value>::type, Arg>
{
    using type = double;
};

// single double; return int
template <typename Arg>
struct Get<typename std::enable_if<std::is_same<Arg, double>::value>::type, Arg>
{
    using type = int;
};

int main()
{
    static_assert(std::is_same<typename Get<double>::type, int>::value, "");
    static_assert(std::is_same<typename Get<int>::type, bool>::value, "");
    static_assert(std::is_same<typename Get<bool, int>::type, double>::value, "");

    return 0;
}

Output:

prog.cpp: In function ‘int main()’:
prog.cpp:29:51: error: ‘type’ in ‘struct Get<double>’ does not name a type
  static_assert(std::is_same<typename Get<double>::type, int>::value, "");
                                                   ^
prog.cpp:29:60: error: template argument 1 is invalid
  static_assert(std::is_same<typename Get<double>::type, int>::value, "");

我将不胜感激能教会我的答案why这并不像我预期的那样工作,而不仅仅是如何修复它。我正在努力寻找有关模板元编程的优质资源,并且到目前为止,我的编程相当随意,这是我非常想解决的问题!

活生生的例子在这里


The template专门化的参数不是原始定义的模板参数。

与原始定义相对应的位于template name.

中的论点template<>专业化的一部分是为匹配专业化而引入的类型。

所以原来的定义:

template <typename Enable, typename...Args>                                 
struct Get;                                                     

1 个或多个类型参数。并且,除非专业化匹配,否则不会定义。

第一专业:

template <typename FirstArg, typename... OtherArgs>                       
struct Get<typename std::enable_if<true>::type, FirstArg, OtherArgs...> {                                                                               
  using type = double;
};

well, std::enable_if<true>::type只是void,所以这与:

template <typename FirstArg, typename... OtherArgs>                       
struct Get<void, FirstArg, OtherArgs...> {                                                                               
  using type = double;
};

因此,如果第一种类型是,则匹配void,并且至少还有一种其他类型。

第二专业:

template <typename Arg>                       
struct Get<typename std::enable_if<std::is_same<Arg, int>::value>::type, Arg> {
  using type = double;
};

所以这会尝试匹配是否有两种类型。第二个是模式匹配。

如果不是的话int,第一个 SFINAE 失败。如果它是一个int,第一个最终是void。所以这匹配Get<void, int> only.

第三专业:

template <typename Arg>
struct Get<typename std::enable_if<std::is_same<Arg, double>::value>::type, Arg> {
  using type = int;
};

同样,这匹配Get<void, double>.

专业化是模式匹配。新加坡金融学会enable_if子句不能进行模式匹配。所以模式匹配运行,然后enable_if条款进行评估。如果失败,则专业化不匹配。如果他们成功了,enable_if子句产生一个类型。生成所有类型(模式和非模式)后,生成的类型列表要么匹配,要么不匹配。

使用此机制的简单方法包括将公共版本转发到详细版本,通过void作为第一种类型,并做你的enable_if在那里工作。

另一种方法是将类型捆绑到类型列表中,例如template<class...>struct types{};,并将其作为一个参数传递,并且void作为第二个参数,然后再次执行 SFINAEvoid.

这是一个例子:

namespace details {
  template<class...>struct types{};
  template<class Types, class=void>
  struct foo;
  template<class T0, class... Ts>
  struct foo<types<T0, Ts...>,typename std::enable_if<
    std::is_same<T0, int>::value && (sizeof...(Ts)>=1)
  >> {
    using type=double;
  };
}
template<class T0, class... Ts>
struct foo:details::foo< details::types<T0, Ts...> >{};

专业化details::foo模式匹配types捆。它的作用是enable_if与这些模式匹配类型的逻辑。这enable_if当且仅当第一个类型是int并且有 1 种或多种附加类型(用于任意一组测试)。

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

如何根据条件和参数数量启用结构体? 的相关文章

随机推荐

  • 传递与参数类型不同的类型

    如果我有一个变量a声明者A a和一个方法m with void m B b 有什么办法可以调用m a 会工作 或者这永远不会起作用 因为a属于类型A and b类型的B If A延伸B 它可以作为参数传递给该函数 如果没有并且A包含适合的值
  • Android 杀死了小米、华为等公司的后台服务

    我需要让我的服务势不可挡 我尝试在启动命令上返回 START STICKY 它在模拟器上运行良好 但是 当从我的设备 小米 mi5s Android 7 上的任务管理器中删除该应用程序时 它不会再次创建自身 Override public
  • C++ - 数组是指针吗? [复制]

    这个问题在这里已经有答案了 可能的重复 C 指针和数组的区别 Is an array in C a pointer 你能澄清一下吗 Thanks 不 但只要您需要它 它就可以衰减为指针 void foo1 char c int main c
  • getFilesDir() 导致空指针异常

    我正处于学习 Java 的早期阶段 但希望有人能解释我在这里做错了什么 大量的谷歌搜索让我头晕目眩 我一直在关注一个教程 该教程展示了如何将 ArrayList 保存到文本文件 然后获取详细信息 我收到以下错误 01 10 19 00 37
  • 分析句子的意思

    有没有什么工具可以分析给定句子的含义 非常感谢您的建议 提前致谢 我也在寻找类似的工具 我最近发现的一件事是这样的sentiment analysis由斯坦福大学的研究人员开发的工具 它提供了分析给定句子的情感的模型 这很有趣 即使这个看似
  • OS X 软件包安装问题:找不到 gfortran 4.8 来构建软件包

    我在使用 Xcode 7 的 mac os x El Capitan 上遇到问题 我使用的是 fortran 6 1 从以下位置下载https gcc gnu org wiki GFortranBinaries 我尝试降级到 fortran
  • 更改 R 中 3d 图中轴标题和标签的方向?

    我有一个问题对于 R 绘图专家来说可能很容易 我需要在R中绘制3D图 我的数据如下 df lt data frame a1 c 489 4 505 8 525 8 550 2 576 6 a2 c 197 8 301 389 8 502 5
  • 如果任务尚未开始,调用Task.wait可能不会等待?

    我正在阅读 Jeffrey Richter 的 clr via c 书 读到任务等待可能并不总是等待时感到不舒服 我引用 当一个线程调用Wait方法时 系统会检查Task是否 线程正在等待的线程已开始执行 如果有的话 那么 调用 Wait
  • $(document).ready 相当于没有 jQuery

    我有一个使用的脚本 document ready 但它不使用 jQuery 中的任何其他内容 我想通过删除 jQuery 依赖来减轻它的负担 我怎样才能实现我自己的 document ready不使用 jQuery 的功能 我知道使用win
  • 使用 Webdriver 的 Eclipse for Java 中的字符编码问题

    我目前正在使用 Eclipse 和 TestNG 通过 java 运行 selenium webdriver 我正在使用 Jexcelapi 从 OpenOffice 电子表格 导入数据 以将我正在测试的网站上的字符串与电子表格中的值进行比
  • 集群环境上的 Spring Batch - Websphere

    我确实设置了一个 Spring Batch 作业 它在单个 JVM 上运行良好 但我需要将其部署到集群环境中 我正在使用 Spring 任务调度程序来安排工作 有没有什么方法可以在集群环境中做到这一点 如果一个节点出现故障 另一个节点应该将
  • Facebook cURL 以我身份发帖?

    创建 Facebook 应用程序 使用 cURL 从应用程序发布消息 但它似乎是由我发布的 我怎样才能从应用程序发布 这是我的 cURL attachment array access token gt token message gt m
  • 由于循环导入而无法导入 opencv

    当尝试在 jupyter 实验室笔记本中导入 opencv 时 import cv2 我收到此错误 AttributeError 部分初始化的模块 cv2 没有属性 gapi wip gst GStreamerPipeline 很可能是由于
  • 如何在 Android 上创建 .csv

    我的目标是从表格创建 csv 文件 以打印报告 然后我可以将此 csv 文件存储到我的 SD 卡中 我已经提到了一些与此类似的问题 但他们要求提供一个 jar 文件 有没有其他方法可以不用jar文件来集成呢 在组件 au com bytec
  • MVVM - WPF DataGrid - AutoGenerateColumn 事件

    我目前正在仔细查看出色的Laurent 的工具包和我有以下问题 从 Blend 4 开始 我为 Loaded 事件添加了一个 EventTrigger 在我的 ViewModel 中我有以下内容 public RelayCommand rc
  • 内部录音程序[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 注意 这不是需要使用麦克风的东西 我想在内部录制音频 我想用 C 或 Java 编写一个程序来记录发送到计算机扬声器的音频数据 最终产品将允许用户点击 录制 按钮 当前正在播放的
  • For 循环影响递归变量

    我正在尝试使用递归创建一个函数 该函数可以从帕斯卡三角形内的任何序列中获取任何项 基本上使用自然数作为第一个集合的加法序列 然后使用之前的每个集合作为加法序列 始终从 1 开始 单纯形数 我目前正在学习 JavaScript 并正在做我已经
  • 自定义hugo学术主题中的“关于”小部件

    我通过 RStudio blogdown 使用hugo academic 主题来构建我的网页 示例页面在这里 https themes gohugo io theme academic 我想添加第二份非学术清单兴趣低于学术的 这可能吗 在配
  • 将字符串中的整数提取到数组中

    我需要提取integers from a String到一个数组中 我已经得到了integers 但我无法将它们放入数组中 public static void main String args String line First numb
  • 如何根据条件和参数数量启用结构体?

    我想创建一个元函数 如果向其传递超过 1 个参数 则返回特定类型 如果仅向其传递一个参数 则返回基于条件的另一种类型 该条件是任意的 因此需要enable if或类似的东西 但对于这个例子 我只是将其作为类型比较 让我们将其简化为以下内容