C++ 如何删除可变模板的最后一个参数

C++ 如何删除可变模板的最后一个参数,c++,c++11,variadic-templates,C++,C++11,Variadic Templates,我有以下结构,我想从索引\u序列中删除最后一个参数: 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_sequenc

我有以下结构,我想从
索引\u序列中删除最后一个参数

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;
};

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, "!");
模板结构索引\u序列;
模板struct at;
模板
结构在
{
静态constexpr std::size\t get\u value()noexcept
{
使用list=std::size_t[];
返回列表{values…}[index];
}
静态constexpr std::size\u t value=get\u value();
}
//试验
//                  -- 0 1 2 3 4
typedef索引顺序偶数;
静态断言(at::value==6,“!”;
再次使用,稍加修改:

#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>{};
#包括
//使用别名进行更清晰的语法
使用Invoke=typename T::type的模板;
模板结构seq{using type=seq;};
模板结构concat;
模板
结构混凝土
:seq{};
模板
使用Concat=Invoke;
模板结构gen_seq;
使用GenSeq=Invoke的模板;
模板
结构gen_seq:Concat{};
模板结构gen_seq:seq{};
模板结构gen_seq:seq{};
现在,通过朋友函数&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>{}));
#包括
#包括
模板
结构类型索引对
{
friend T my_declval(类型索引对,
std:积分(u常数);
};
模板
结构pop_back_helper;
模板
结构pop_back_辅助对象
{
结构基:类型\索引\对。。。
{};
模板
使用join=std::tuple;
};
模板
自动推断(顺序,顺序)
->typename pop\u back\u助手
::模板联接
{return{};}//实际上不需要定义
模板
使用pop_back=decltype(推断(gen_seq{},
gen_seq{});
用法示例:

#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>{} );
}
#包括
模板
无效漂亮的印刷品(T)
{

std::cout有我自己的问题的解决方案:

template< int ...i> struct seq{};

   // GCC couldn't optimize sizeof..(i) , 
   //see http://stackoverflow.com/questions/19783205/why-sizeof-t-so-slow-implement-c14-make-index-sequence-without-sizeof
   //so I use direct variable `s` instead of it.
   // i.e.  s == number of variadic arguments in `I`.
    template< int s, typename I, typename J > struct concate;

    template< int s, int ...i, int ...j>
    struct concate<s, seq<i...>, seq<j...> >
    { 
        typedef seq<i..., (s  + j)...> type;
    };

    template<int n> struct make_seq_impl;
    template< int n> using make_seq = typename make_seq_impl<n>::type;

    template<> struct make_seq_impl<0>{ typedef seq<> type;};
    template<> struct make_seq_impl<1>{ typedef seq<0> type;};

    template<int n> struct make_seq_impl: concate< n/2, make_seq<n/2>, make_seq<n-n/2>>{};

    //----------------------------------------------------
    // Our solution: 

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

    template< typename IndexSequence> struct pop_back;

    // empty index_sequence 
    template<>struct pop_back< index_sequence<> >
    { 
        typedef index_sequence<> type;
    };

    template< std::size_t ...i>
    struct pop_back< index_sequence<i...> >
    {
         static constexpr std::size_t size = sizeof...(i);
         static constexpr std::size_t values[] = {i...};

         template< typename sq> struct apply;
         template< int ...j> struct apply< seq<j...> >
         {
             typedef index_sequence< values[j]... > type;
         };

         typedef typename apply< make_seq< size - 1 > >::type type;
    };

    // test
    int main()
    {
         typedef index_sequence< 2, 4, 6, 8, 10>  ievens;

         typedef pop_back< ievens>::type  jevens;

         static_assert( std::is_same< jevens, index_sequence<2,4,6,8> >::value ,"!");
}
templatestruct seq{};
//GCC无法优化..(i)的大小,
//看http://stackoverflow.com/questions/19783205/why-sizeof-t-so-slow-implement-c14-make-index-sequence-without-sizeof
//所以我用直接变量's'代替它。
//即s==在“i”中变量参数的数量。
模板struct concate;
模板
结构混凝土
{ 
typedef-seq-type;
};
模板结构make_seq_impl;
模板使用make_seq=typename make_seq_impl::type;
模板结构make_seq_impl{typedef seq type;};
模板结构make_seq_impl{typedef seq type;};
模板结构make_seq_impl:concate{};
//----------------------------------------------------
//我们的解决方案:
模板结构索引\u序列{};
模板struct pop_back;
//空索引序列
templatestruct pop\u back<索引\u序列>
{ 
类型定义索引_序列类型;
};
模板
结构弹出返回<索引序列>
{
静态constexpr std::size\u t size=sizeof…(i);
静态constexpr std::size_t值[]={i..};
模板结构应用;
模板结构应用
{
typedef索引_序列<值[j]…>类型;
};
typedef typename apply>::type类型;
};
//试验
int main()
{
typedef索引_序列<2,4,6,8,10>ieven;
typedef pop_back:输入jevens;
静态断言(std::is_same::value,“!”;
}

您是想避免深度递归只是作为练习,还是处理的列表太大,会破坏编译器?我在stackoverflow中阅读了一些关于如何避免深度递归的技巧,所以我相信在我的情况下也可以避免深度递归。只有我自己找不到。这是您的第二个帐户吗?如果是,欢迎回来;)谢谢。事实上这是我的第一个帐户,Khurshid Normuradov是第二个。我删除了我的facebook帐户,所以我的第二个帐户也被删除了,因为我是从facebook帐户登录stackoverflow的。我已经多次体验过如何减少编译时间的问题。我喜欢boost mpl库-这是c++03的优秀库,但实际上现在是c++11(GCC、CLang、Intel(完整)、Visual Studio(部分)支持C++11)所以我用多变的模板来说明。我知道很多公司直到使用C++ 03,因为它测试很多年了,所有C++编译器都能很好的优化。但是,我相信从明年或接下来的两年,C++ 11完全取代C++ 03。即使使用O(log),也需要O(n)实例化,使用甚至更快。实例化深度。例如,执行第n个元素K-1次,其中K是原始序列中的类型数。我希望具有编译器/ASM专业知识的人加入进来-直觉上,我认为这不会慢(就像在编译后一样),因为“助手”会减少,有序的指令会内联。()@dyp,假设我的直觉是正确的,您的实例化和实例化深度将对应于编译时行为-不包括相关的编译时算法,如reduces-这没有什么可嘲笑的,但应该与runtime.IIRC和带有标记分派的ADL区分开来,许多递归层除了jug之外什么也不做gle标记在编译时被(或可以)压缩,只留下尾部调用,就像中间调用一样。丢弃的标记不会影响任何运行时/资源,甚至不会膨胀。尽管如此,我理解编译时行为也会影响正确性,例如,由于“触底”而导致的编译失败当中间过程超过编译器的最大递归深度时。
template< int ...i> struct seq{};

   // GCC couldn't optimize sizeof..(i) , 
   //see http://stackoverflow.com/questions/19783205/why-sizeof-t-so-slow-implement-c14-make-index-sequence-without-sizeof
   //so I use direct variable `s` instead of it.
   // i.e.  s == number of variadic arguments in `I`.
    template< int s, typename I, typename J > struct concate;

    template< int s, int ...i, int ...j>
    struct concate<s, seq<i...>, seq<j...> >
    { 
        typedef seq<i..., (s  + j)...> type;
    };

    template<int n> struct make_seq_impl;
    template< int n> using make_seq = typename make_seq_impl<n>::type;

    template<> struct make_seq_impl<0>{ typedef seq<> type;};
    template<> struct make_seq_impl<1>{ typedef seq<0> type;};

    template<int n> struct make_seq_impl: concate< n/2, make_seq<n/2>, make_seq<n-n/2>>{};

    //----------------------------------------------------
    // Our solution: 

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

    template< typename IndexSequence> struct pop_back;

    // empty index_sequence 
    template<>struct pop_back< index_sequence<> >
    { 
        typedef index_sequence<> type;
    };

    template< std::size_t ...i>
    struct pop_back< index_sequence<i...> >
    {
         static constexpr std::size_t size = sizeof...(i);
         static constexpr std::size_t values[] = {i...};

         template< typename sq> struct apply;
         template< int ...j> struct apply< seq<j...> >
         {
             typedef index_sequence< values[j]... > type;
         };

         typedef typename apply< make_seq< size - 1 > >::type type;
    };

    // test
    int main()
    {
         typedef index_sequence< 2, 4, 6, 8, 10>  ievens;

         typedef pop_back< ievens>::type  jevens;

         static_assert( std::is_same< jevens, index_sequence<2,4,6,8> >::value ,"!");
}