如何使用模板创建排序映射整数索引

2024-01-10

我有数据结构:

template <int...I> struct index {};

template <typename...T> struct data {};

template <int I, int J> struct X
{
   static constexpr int i = I;
   static constexpr int j = J;
};

typedef data< X<0,4>, X<1,2>, X<2,1>, X<1,6>, X<1,3> > data_t;

其中 data 不包含重复项,并且索引 J 很小,范围为 0-31。

我想创建一个静态索引,其中包含索引 I 等于某个给定值(例如 I=1)的所有 X 的 data 中的位置,按索引 J 排序。它是“排序”位我觉得这很困难。

例如,我想实现一个类 build_index :

typedef build_index<1,data>::type_t index_t;

生成与以下相同:

typedef index<1, 4, 3> index_t;

它反映了按 J 排序的元素 X(1,J) 在 data 中的位置: X(1,2) 位于数据(1)、X(1,3) 位于数据(4)、X(1,6) 位于数据(3)

我不想使用 STL,因为它不适用于 gcc-avr,尽管我可以移植选定的片段。


当您在 C++ 模板编程中遇到复杂的问题时,尝试将其分解为几个较小的步骤(就像大多数编程问题一样)会很有帮助。这是一条可能的路径:

  1. 选择与所选 I 匹配的 X 并将它们存储在新的数据类型中,用位置替换 I(为此使用递归)
  2. 按 J 对 selected_data 中的 X 进行排序。我认为这写起来有点烦人。也许您应该为此创建一个单独的问题。
  3. 从已排序和选定的 X 中提取位置

这是相应的代码。我在用std::conditional,但这当然很容易更换。我在用std::is_same在测试中,您当然并不真正需要它(否则实现起来会很简单)。

你的东西 + std::conditional 和 std::is_same 的实用程序标头

#include <utility>

template <int... I>
struct index
{
};

template <typename... T>
struct data
{
};

template <int I, int J>
struct X
{
  static constexpr int i = I;
  static constexpr int j = J;
};

typedef data<X<0, 4>, X<1, 2>, X<2, 1>, X<1, 6>, X<1, 3>> data_t;

提取Xs 匹配I我们正在寻找并替换is 与位置。

template <int Pos, int I, typename Extracted, typename Rest>
struct ExtractImpl;

template <int Pos, int I, typename... ExtractedX>
struct ExtractImpl<Pos, I, data<ExtractedX...>, data<>>
{
  using type = data<ExtractedX...>;
};

template <int Pos, int I, typename... ExtractedX, typename T, typename... Rest>
struct ExtractImpl<Pos, I, data<ExtractedX...>, data<T, Rest...>>
{
  using type = typename std::conditional<
      (T::i == I),
      typename ExtractImpl<Pos + 1,
                           I,
                           data<ExtractedX..., X<Pos, T::j>>,
                           data<Rest...>>::type,
      typename ExtractImpl<Pos + 1, I, data<ExtractedX...>, data<Rest...>>::
          type>::type;
};

template <int I, typename Data>
struct Extract
{
  using type = typename ExtractImpl<0, I, data<>, Data>::type;
};

using extracted = typename Extract<1, data_t>::type;
static_assert(std::is_same<extracted, data<X<1, 2>, X<3, 6>, X<4, 3>>>::value, "");

按 J 排序。这是通过将元素增量插入排序列表来完成的。可能有更优雅的方法来做到这一点。

template <typename T, typename LessList, typename RestList>
struct insert_impl;

template <typename T, typename... Lesser>
struct insert_impl<T, data<Lesser...>, data<>>
{
  using type = data<Lesser..., T>;
};

template <typename T, typename... Lesser, typename Next, typename... Rest>
struct insert_impl<T, data<Lesser...>, data<Next, Rest...>>
{
  using type = typename std::conditional<
      (T::j < Next::j),
      data<Lesser..., T, Next, Rest...>,
      typename insert_impl<T, data<Lesser..., Next>, data<Rest...>>::type>::
      type;
};

template <typename T, typename SortedList>
struct insert
{
  using type = typename insert_impl<T, data<>, SortedList>::type;
};

template <typename SortedList, typename UnsortedList>
struct SortImpl;

template <typename SortedList>
struct SortImpl<SortedList, data<>>
{
  using type = SortedList;
};

template <typename SortedList, typename T, typename... UnsortedX>
struct SortImpl<SortedList, data<T, UnsortedX...>>
{
  using type = typename SortImpl<typename insert<T, SortedList>::type,
                                 data<UnsortedX...>>::type;
};

template <typename UnsortedList>
struct Sort
{
  using type = typename SortImpl<data<>, UnsortedList>::type;
};

using sorted = typename Sort<extracted>::type;
static_assert(std::is_same<sorted, data<X<1, 2>, X<4, 3>, X<3, 6>>>::value, "");

最后,提取您要查找的索引:

template <typename List>
struct Indexes;

template <typename... Data>
struct Indexes<data<Data...>>
{
  using type = index<Data::i...>;
};

using result = typename Indexes<sorted>::type;
static_assert(std::is_same<result, index<1, 4, 3>>::value, "");

警告:虽然我在代码中没有看到任何问题,但除了您的示例之外,我还没有对其进行测试......

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

如何使用模板创建排序映射整数索引 的相关文章

随机推荐

  • 从 cuda 内核中访问类数据成员 - 如何设计正确的主机/设备交互?

    我一直在努力改变一些cuda C代码变成更面向对象的代码 但以我目前对cuda运行机制的理解来说 我的目标似乎并不容易实现 对于这种情况我也找不到很好的解释 毕竟这可能是不可能的 我有一个global类的对象myClass保存一个要填充到内
  • 在命名空间内设计

    我试图将我的 Rails 项目拆分为普通用户的前端和管理员的后端 因此 我创建了一个命名空间 admin 以便我可以在地图管理中轻松控制管理特定的控制器方法 布局 身份验证 我仅使用 Devise 来注册 验证我的管理员 因为它仅用于管理员
  • 未找到:当我使用张量流和烧瓶加载模型时,容器本地主机不存在

    我是一个研究深度学习的新手 我使用张量流加载保存的模型并使用 Flask 创建 API 但收到错误 容器本地主机不存在 当我预测时 请帮我解决它 谢谢 张量流版本 1 13 1 喀拉拉邦版本 2 2 4 烧瓶版本 1 0 3 我通过命令 p
  • 如何在gcc中获取当前的c方言?

    C 编程新手 In gcc std设置编译的 C 标准 例如gcc std c99 可以知道当前制定的是哪个C标准吗 存在以各种模式定义的各种预处理器符号 您可以使用gcc E dM x c dev null获取所有预定义的预处理器符号的转
  • 如何在oracle sql中连接2个具有不同记录数和列数的查询?

    我有三张桌子 Employee leave EmployeeID Time Period leave type Employee EID Department Designation leave eligibility Department
  • 无法将依赖项自动连接到自定义验证器中

    我希望使用自定义验证器来验证我的对象属性 并且我需要注入一些 bean 所以我无法自动装配任何 bean 并且出现此异常 java lang NoSuchMethodException com MyValidatorValidator
  • 一起使用 jQuery :has() 和 :contains() 选择器

    我有一个包含标签元素的列表项元素 我想选择列表项元素 has 选择器 标签元素内有我想要匹配的文本 contains 是否可以用一行 jQuery 完成这两件事 如果不是 那么根据子标签元素的内容选择 li 元素的优雅方法是什么 li li
  • onNewIntent() 在手机唤醒之前不会触发

    我发现了一些有趣的行为 但不知道为什么或如何解决它 该活动是一个单任务活动 这意味着 onNewIntent 是针对该活动的 而该活动位于堆栈顶部 这工作得很好 很好 当手机屏幕打开时 然而 一旦屏幕关闭 直到手机 唤醒 并且此时 onNe
  • Angular 2树仅显示根节点

    angular2 tree 库有一个简单的基本用法 example https angular2 tree readme io docs basic usage 但是 当我将其放入我的项目中时 仅渲染根节点 换句话说 树应该有父母 root
  • 不同scanf格式之间的区别[重复]

    这个问题在这里已经有答案了 我目前正在通过阅读教科书为进入编程学校做准备 有一个问题我不明白 课本上也没有给出答案 PS 我在网上学习了一些 C C 但从未参加过正确教授的编程课程 因此我在某些概念上遇到了困难 问 对于以下每一对 scan
  • 同一文件的重复资源警告

    我收到这个相当令人困惑的编译器警告 DCC 警告 W1056 警告 重复资源 类型 14 ICON 集团 ID MAICON 文件 C dev dispense trunk dev source mountaintop dispense M
  • 自定义文本块,将其内容转换为不同的颜色

    我将编写一个自定义文本块来分割其文本内容 它将根据条件使文本具有不同的颜色 并且文本将用逗号分隔 逗号将保持黑色 我不知道如何开始 您能提供启动方面的帮助吗 提前致谢 下面的用户控件使用项目控件以某种随机颜色显示每个标记 Usage
  • 合并2个链表并附加到链表的末尾c ++

    到目前为止我还没有太多 但我正在尝试掌握使用链表的窍门 Struct struct Node int value Node next 如何将节点添加到列表末尾 我只是想获取一个列表头的指针和一个 int 值作为新节点添加 当我尝试运行当前的
  • Numpy 中从一个音高到另一个音高的正弦波滑奏

    我一直在开发一个程序 我需要缓慢而平稳地将正弦波的音调从一个音调更改为另一个音调 我能够获得在任何给定时刻音调应有的频率数组 例如 440 526 5 634 2 794 8 880 尽管更长很多 但似乎我无法实际应用该频率来一波 我最好的
  • 如何从 coverity-scan 中删除项目

    我已经注册了一个项目覆盖扫描 https scan coverity com在过去 我现在想从覆盖扫描中删除该项目 或者至少从我的仪表板上删除该项目 但最好我想完全删除该项目 我被困住了 因为网络界面中似乎没有这样的选项 我错过了什么吗 你
  • RxJS first() for Observable.of() - 序列中没有元素

    对于我的测试 我试图用以下方法模拟事件流Observable of 但当我尝试时 const actions Observable of in the function that is tested actions filter actio
  • VS 2015编译cocos2d-x 3.3错误“fatal error C1189: #error: MacroDefinition of snprintf与标准库函数声明冲突”

    当我使用Visual Studio 2015编译cocos2d x 版本3 3 时 出现错误 说 致命错误 C1189 error snprintf 的宏定义与标准库函数声明冲突 编译源文件 base s3tc cpp 源代码是 ifdef
  • 使用Delphi消费oData服务建议

    我即将启动一个需要 Delphi XE Windows 32 客户端来使用的项目oData http www odata org 网络服务 我可以使用一些粗略和可读的测试代码正确查询服务 但是编写一个框架来处理 oData 协议 所有过滤
  • 如何使用 Kotlin 修复此错误,找不到 Fragment 构造函数?

    我正在开发Android使用 Kotlin 的应用程序 在我的应用程序中包含Tab with ViewPager所以我实现了两个选项卡 当我移动到另一个活动并压缩到选项卡视图活动时 应用程序将停止并且logcat显示下面的错误 java l
  • 如何使用模板创建排序映射整数索引

    我有数据结构 template