如何删除可变参数模板的最后一个参数 [英] How to remove last argument of variadic template

查看:40
本文介绍了如何删除可变参数模板的最后一个参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下结构,我想从 index_sequence 中删除最后一个参数:

I have following structure, I want remove last argument from index_sequence :

template< std::size_t ... values>
struct index_sequence{};

// I need something like
template< typename IndexSequence>
struct pop_back;

template< std::size_t ... values >
struct pop_back< index_sequence< values... > >
{
    typedef index_sequence< /** values except last one*/ > type;
};

如何实现此 pop_back 结构?

How to implement this pop_back structure?

我知道实现,只需要深度递归,我想要没有深度递归实例化.

I know implementation, only it requires deep recursion, I want without deep recursion instantination.

我的实现:

template< std::size_t i, typename IndexSequence >
struct insert_head;

template< std::size_t i, std::size_t ...values>
struct insert_head< i, index_sequence<values...> >
{
   typedef index_sequence< i, values... > type;
};

template< > 
struct pop_back< index_sequence<> > 
{ 
typedef index_sequence<> type; // no element will removed 
}; 

template< std::size i > struct pop_back< index_sequence< i > >
{
   typedef index_sequence<> type; // i - will removed
};

template< std::size_t i, std::size_t ...values> 
struct pop_back< index_sequence<i,values...>>
{
    typedef typename pop_back< index_sequence<values...> >::type tail;
    typedef typename insert_head< i, tail>::type type;
};


Edit2:另一个有用的算法,选择第i个元素!!!

template< std::size ...i> struct index_sequence;

template< std::size_t index, typename IndexSeq> struct at;

template< std::size_t index, std::size_t ... values> 
struct at< index, index_sequence<values...> >
{
     static constexpr std::size_t get_value()noexcept
     {
          using list = std::size_t [];
          return list{ values...}[index];
     }

    static constexpr std::size_t value = get_value();
}

// test
//                  -- 0 1 2 3 4
typedef index_sequence<2,4,6,8,10>  even_t;

static_assert( at<2, even_t>::value == 6, "!");

推荐答案

再次使用 Xeo

Again, using Xeo's O(logN) instantiation depth version of gen_seq, slightly modified:

#include <cstddef>

    // using aliases for cleaner syntax
    template<class T> using Invoke = typename T::type;

    template<std::size_t...> struct seq{ using type = seq; };

    template<class S1, class S2> struct concat;

    template<std::size_t... I1, std::size_t... I2>
    struct concat<seq<I1...>, seq<I2...>>
      : seq<I1..., (sizeof...(I1)+I2)...>{};

    template<class S1, class S2>
    using Concat = Invoke<concat<S1, S2>>;

    template<std::size_t N> struct gen_seq;
    template<std::size_t N> using GenSeq = Invoke<gen_seq<N>>;

    template<std::size_t N>
    struct gen_seq : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{};

    template<> struct gen_seq<0> : seq<>{};
    template<> struct gen_seq<1> : seq<0>{};

现在,通过朋友功能&使用我以前的技巧之一ADL:

Now, using one of my former tricks via a friend function & ADL:

#include <tuple>
#include <type_traits>

template<class T, std::size_t I>
struct type_index_pair
{
    friend T my_declval(type_index_pair,
                        std::integral_constant<std::size_t, I>);
};

template<class, class>
struct pop_back_helper;

template<class... TT, std::size_t... Is>
struct pop_back_helper<std::tuple<TT...>, seq<Is...>>
{
    struct base : type_index_pair<TT, Is>...
    {};

    template<std::size_t... Is2>
    using join = std::tuple< decltype(my_declval(base{},
                             std::integral_constant<std::size_t, Is2>{}))... >;
};

template<class... TT, std::size_t... Is, std::size_t... Is2>
auto deduce(seq<Is...>, seq<Is2...>)
-> typename pop_back_helper<std::tuple<TT...>, seq<Is...>>
   ::template join<Is2...>
{  return {};  } // definition not required, actually

template<class... TT>
using pop_back = decltype(deduce<TT...>(gen_seq<sizeof...(TT)>{},
                                        gen_seq<sizeof...(TT)-1>{}));

用法示例:

#include <iostream>
template<class T>
void pretty_print(T)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main()
{
    pretty_print( pop_back<int, bool, char, double>{} );
    pretty_print( pop_back<double, int, int>{} );
}

我对此并不特别满意,因为它需要两个 序列 ADL(AFAIK需要资源,而且速度较慢).也许我几天后就能提出更好的建议.

I'm not particularly happy with it, as it requires two sequences plus the ADL (which requires resources and is slow, AFAIK). Maybe I'll be able to come up with something better in one of next days.

这篇关于如何删除可变参数模板的最后一个参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆