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

C++ 如何使用模板创建排序映射整数索引,c++,sorting,c++11,metaprogramming,c++14,C++,Sorting,C++11,Metaprogramming,C++14,我有以下数据结构: 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>

我有以下数据结构:

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;
模板结构索引{};
模板结构数据{};
模板结构X
{
静态constexpr int i=i;
静态constexpr int j=j;
};
typedef数据data\u t;
其中数据不包含重复项且索引J较小,范围为0-31

我想创建一个静态索引,它包含所有X的数据位置,索引I等于某个给定值(例如I=1),按索引J排序。我发现“排序”位比较困难

例如,我想实现一个类build_索引,以便:

typedef build_index<1,data>::type_t index_t;
typedef build_index::type_t index\t;
生成与以下内容相同的内容:

typedef index<1, 4, 3> index_t;
typedef索引;
它反映了由J排序的元素X(1,J)在数据中的位置: 数据(1)处的X(1,2),数据(4)处的X(1,3),数据(3)处的X(1,6)


<>我宁愿不使用STL,因为它不适用于GCC AVR,虽然我可以选择选中的片段。

< P>当你面对C++模板编程中的复杂事物时,它主要有助于将它分解成几个小步骤(就像大多数编程问题一样)。以下是一个可能的路径:

  • 选择与所选I匹配的X,并将其存储在新的数据类型中,用位置替换I(对此使用递归)
  • 按J对所选_数据中的X进行排序。我认为这写起来有点烦人。也许你应该为此单独提出一个问题
  • 从已排序和选定的X中提取位置
  • 这是相应的代码。我使用的是
    std::conditional
    ,当然这很容易替换。我在测试中使用的是
    std::is_same
    ,当然,您并不真正需要它(否则实现它会很简单)

    std::conditional和std::的stuff+实用程序头是相同的

    #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;
    
    按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, "");
    
    模板
    结构插入\u impl;
    模板
    结构插入\u impl
    {
    使用类型=数据;
    };
    模板
    结构插入\u impl
    {
    使用type=typename std::conditional<
    (T::j::
    类型;
    };
    模板
    结构插入
    {
    使用type=typename插入\ u impl::type;
    };
    模板
    结构SortImpl;
    模板
    结构SortImpl
    {
    使用类型=分类列表;
    };
    模板
    结构SortImpl
    {
    使用type=typename SortImpl::type;
    };
    模板
    结构排序
    {
    使用type=typename SortImpl::type;
    };
    使用sorted=typename排序::type;
    静态断言(std::is_same::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, "");
    
    模板
    结构索引;
    模板
    结构索引
    {
    使用类型=索引;
    };
    使用result=typename索引::type;
    静态断言(std::is_same::value,“”);
    

    警告:虽然我没有发现代码中有任何问题,但除了您的示例之外,我没有对其进行测试…

    我将分享我对这个问题的处理方法,我认为这是一种巧妙的方法。我使用了C++11
    std::conditional
    、C++14
    std::integer\u sequence
    std::make\u integer\u sequence
    ,所有这些都可以在线找到

    让我们从您拥有的数据结构开始

    template <int... Is> struct index {};
    template <typename... Ts> struct list {};
    template <int L, int R> struct pair {};
    
    现在我们进入
    build\u index
    。我们在已知的
    [0,32)
    范围内执行桶排序。我们本可以使用通用排序算法,但作弊更有趣

    template <int N, typename T> struct build_index;
    
    // e.g., `build_index<
    //            1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>`
    template <int N, int... Ls, int... Rs>
    struct build_index<N, list<pair<Ls, Rs>...>> {
      // Filter for pairs where `N == lhs`, and replace the `lhs` with the index.
      template <int... Is>
      static auto filter(std::integer_sequence<int, Is...>)
          -> concat_t<std::conditional_t<N == Ls, list<pair<Is, Rs>>, list<>>...>;
    
      // e.g., `list<pair<1, 2>, pair<3, 6>, pair<4, 3>>`
      using filtered =
          decltype(filter(std::make_integer_sequence<int, sizeof...(Ls)>{}));
    
      // `get<I>(set)` returns the `lhs` if `set` can implicitly convert to
      // `pair<lhs, I>` for some `lhs`, and nothing otherwise.
      template <typename... Ts> struct set : Ts... {};
      template <int I, int L> static list<index<L>> get(pair<L, I>);
      template <int I> static list<> get(...);
    
      // We invoke `get<I>` for `I` in `[0, 32)` to sort `filtered`.
      template <int... Is, typename... Ts>
      static auto sort(std::integer_sequence<int, Is...>, list<Ts...>)
          -> concat_t<decltype(get<Is>(set<Ts...>{}))...>;
    
      // e.g., `list<index<1>, index<4>, index<3>>`
      using sorted =
          decltype(sort(std::make_integer_sequence<int, 32>{}, filtered{}));
    
      // e.g., `list<1, 4, 3>`
      template <int... Is> static index<Is...> indices(list<index<Is>...>);
      using type = decltype(indices(sorted{}));
    };
    
    template <int N, typename... Ts>
    using build_index_t = typename build_index<N, Ts...>::type;
    
    模板结构构建索引;
    //例如,“构建索引”<
    //1、清单`
    模板
    结构构建索引{
    //筛选其中'N==lhs'的对,并用索引替换'lhs'。
    模板
    静态自动过滤器(标准::整数\u序列)
    ->康考特;
    //例如,`列表`
    使用过滤=
    decltype(filter(std::make_integer_sequence{}));
    //如果`set`可以隐式转换为,则`get(set)`返回`lhs`
    //对于某些'lhs','pair',没有其他的。
    模板结构集:Ts..{};
    模板静态列表获取(对);
    模板静态列表获取(…);
    //我们在`[0,32)`中为` I`调用` get`来对`过滤'进行排序。
    模板
    静态自动排序(std::integer\u序列,列表)
    ->康考特;
    //例如,`列表`
    使用排序=
    decltype(排序(std::make_integer_sequence{},filtered{}));
    //例如,`列表`
    模板静态索引(列表);
    使用type=decltype(索引(排序{}));
    };
    模板
    使用build\u index\u t=typename build\u index::type;
    
    我们得到:

    using index_t = build_index_t<
        1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>>;
    static_assert(std::is_same<index<1, 4, 3>, index_t>::value, "");
    
    使用索引\u t=build\u index\t<
    1、列表>;
    静态断言(std::is_same::value,“”);
    
    允许您更改数据吗?您是否考虑过Boost元编程库(Boost.mpl)例如,你可以自己滚动排序,但是使用别人已经写的更容易。你的问题用C++ 11来标记。如果你可以使用C++ 14,它会简单很多。@ 5Go12EDER:我可以使用C++。14@fish2000在C++ 14中,您可以简单地将信息存储在<代码> CONTXPRP</CUSE>数组中,并使用普通的C++代码进行SEA。归档和排序。由于标准库还没有相关的
    constexpr
    函数,你必须自己编写它们,这就是为什么它仍然不是一个简单的任务,这也是为什么我还没有写答案的原因。非常好!谢谢。+1祝贺你喜欢它:-)顺便说一句:当你认为你得到了你想要的答案,并且不期望得到什么的时候如果您希望尽快到达,您应该将一个答案标记为正确答案。目前,您所有的问题都列为未回答。
    template <int N, typename T> struct build_index;
    
    // e.g., `build_index<
    //            1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>`
    template <int N, int... Ls, int... Rs>
    struct build_index<N, list<pair<Ls, Rs>...>> {
      // Filter for pairs where `N == lhs`, and replace the `lhs` with the index.
      template <int... Is>
      static auto filter(std::integer_sequence<int, Is...>)
          -> concat_t<std::conditional_t<N == Ls, list<pair<Is, Rs>>, list<>>...>;
    
      // e.g., `list<pair<1, 2>, pair<3, 6>, pair<4, 3>>`
      using filtered =
          decltype(filter(std::make_integer_sequence<int, sizeof...(Ls)>{}));
    
      // `get<I>(set)` returns the `lhs` if `set` can implicitly convert to
      // `pair<lhs, I>` for some `lhs`, and nothing otherwise.
      template <typename... Ts> struct set : Ts... {};
      template <int I, int L> static list<index<L>> get(pair<L, I>);
      template <int I> static list<> get(...);
    
      // We invoke `get<I>` for `I` in `[0, 32)` to sort `filtered`.
      template <int... Is, typename... Ts>
      static auto sort(std::integer_sequence<int, Is...>, list<Ts...>)
          -> concat_t<decltype(get<Is>(set<Ts...>{}))...>;
    
      // e.g., `list<index<1>, index<4>, index<3>>`
      using sorted =
          decltype(sort(std::make_integer_sequence<int, 32>{}, filtered{}));
    
      // e.g., `list<1, 4, 3>`
      template <int... Is> static index<Is...> indices(list<index<Is>...>);
      using type = decltype(indices(sorted{}));
    };
    
    template <int N, typename... Ts>
    using build_index_t = typename build_index<N, Ts...>::type;
    
    using index_t = build_index_t<
        1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>>;
    static_assert(std::is_same<index<1, 4, 3>, index_t>::value, "");