How to create a sorted mapping integer index with templates

前端 未结 2 650
情话喂你
情话喂你 2021-02-10 07:34

I have the data structure:

template  struct index {};

template  struct data {};

template  struct X
{
            


        
2条回答
  •  长情又很酷
    2021-02-10 08:28

    When you are facing something complex in C++ template programming, it mostly helps to try to break it into several smaller steps (like with most programming problems). Here is a possible path:

    1. Select the X which match the selected I and store them in a new data type replacing the I with the position (use recursion for this)
    2. Sort the X in the selected_data by J. This is a bit annoying to write, I think. Maybe you should create a separate question for that.
    3. Extract the positions from the sorted and selected X

    And here is the corresponding code. I am using std::conditional, but that is easy to replace of course. I am using std::is_same in the tests, you do not really need that of course (and it would be trivial to implement otherwise).

    Your stuff + utility header for std::conditional and std::is_same

    #include 
    
    template 
    struct index
    {
    };
    
    template 
    struct data
    {
    };
    
    template 
    struct X
    {
      static constexpr int i = I;
      static constexpr int j = J;
    };
    
    typedef data, X<1, 2>, X<2, 1>, X<1, 6>, X<1, 3>> data_t;
    

    Extract the Xs that match the I we are looking for and replace the is with the position.

    template 
    struct ExtractImpl;
    
    template 
    struct ExtractImpl, data<>>
    {
      using type = data;
    };
    
    template 
    struct ExtractImpl, data>
    {
      using type = typename std::conditional<
          (T::i == I),
          typename ExtractImpl>,
                               data>::type,
          typename ExtractImpl, data>::
              type>::type;
    };
    
    template 
    struct Extract
    {
      using type = typename ExtractImpl<0, I, data<>, Data>::type;
    };
    
    using extracted = typename Extract<1, data_t>::type;
    static_assert(std::is_same, X<3, 6>, X<4, 3>>>::value, "");
    

    Sort by J. This is done by incrementally inserting elements into a sorted list. There might be more elegant ways to do it.

    template 
    struct insert_impl;
    
    template 
    struct insert_impl, data<>>
    {
      using type = data;
    };
    
    template 
    struct insert_impl, data>
    {
      using type = typename std::conditional<
          (T::j < Next::j),
          data,
          typename insert_impl, data>::type>::
          type;
    };
    
    template 
    struct insert
    {
      using type = typename insert_impl, SortedList>::type;
    };
    
    template 
    struct SortImpl;
    
    template 
    struct SortImpl>
    {
      using type = SortedList;
    };
    
    template 
    struct SortImpl>
    {
      using type = typename SortImpl::type,
                                     data>::type;
    };
    
    template 
    struct Sort
    {
      using type = typename SortImpl, UnsortedList>::type;
    };
    
    using sorted = typename Sort::type;
    static_assert(std::is_same, X<4, 3>, X<3, 6>>>::value, "");
    

    Finally, extract the indexes you are looking for:

    template 
    struct Indexes;
    
    template 
    struct Indexes>
    {
      using type = index;
    };
    
    using result = typename Indexes::type;
    static_assert(std::is_same>::value, "");
    

    Word of warning: While I don't see any problems in the code, I have not tested it beyond your example...

提交回复
热议问题