How can I pull variadic template arguments off from the tail instead of the head?

后端 未结 4 1177
离开以前
离开以前 2021-02-04 13:10

For silly reasons I\'ll not go into here, I need the commented out line to work and the line above it it to not work:

template
         


        
4条回答
  •  梦谈多话
    2021-02-04 13:25

    I've made my code work a little bit like lists in Haskell - because, well, TMP is purely functional language inside C++.

    add_to_pack is equivalent to Haskell's list constructor (:). drop_from_end is implemented as (in Haskell notation) \x list -> take (length list - x) list, where take n just takes first n elements of the list.

    I suppose you could use std::tuple directly instead of pack, but I liked this solution better, because it doesn't misuse tuple as template parameter pack holder. :)

    Here's the code:

    #include 
    #include  // for std::conditional
    
    
    template 
    struct pack
    { };
    
    
    template 
    struct add_to_pack;
    
    template 
    struct add_to_pack>
    {
      typedef pack type;
    };
    
    
    template 
    struct convert_to_tuple;
    
    template 
    struct convert_to_tuple>
    {
      typedef std::tuple type;
    };
    
    
    template 
    struct take;
    
    template 
    struct take
    {
      typedef pack<> type;
    };
    
    template 
    struct take
    {
      typedef
        typename std::conditional<
          (N > 0),
          typename add_to_pack<
            Head,
            typename take<
              N - 1,
              Tail...
            >::type
          >::type,
          pack<>
        >::type type;
    };  
    
    
    template 
    struct drop_from_end
    {
      // Add these asserts if needed.
      //static_assert(N >= 0,
      //  "Cannot drop negative number of elements!");
    
      //static_assert(N <= static_cast(sizeof...(A)),
      //  "Cannot drop more elements than size of pack!")
    
      typedef
        typename convert_to_tuple<
          typename take<
            static_cast(sizeof...(A)) - N,
            A...
          >::type
        >::type type;
    };
    
    
    int main()
    {
      drop_from_end<2, const char*, double, int, int>::type b{"pi", 3.1415};
    }
    

    And here's the code at work: via ideone.com.


    The take struct is more or less equivalent to following Haskell code:

    take n []     = []
    take n (x:xs)
      | n > 0     = x : take (n - 1) xs
      | otherwise = []
    

提交回复
热议问题