为了账号安全,请及时绑定邮箱和手机立即绑定

C+14 make_INTEGER序列的实现

C+14 make_INTEGER序列的实现

C++
凤凰求蛊 2019-06-23 14:37:26
C+14 make_INTEGER序列的实现我试图实现C+14别名模板make_integer_sequence,它简化了类模板的创建。integer_sequence.template< class T, T... I> struct integer_sequence{     typedef T value_type;     static constexpr size_t size() noexcept { return sizeof...(I) ; }};     template< class T, T N>using make_integer_sequence = integer_sequence< T, 0,1,2, ... ,N-1 >; // only for illustration.实施make_integer_sequence我们需要一个助手结构make_helper.template< class T , class N >using make_integer_sequence = typename make_helper<T,N>::type;实施make_helper不太难。template< class T, T N, T... I >struct make_helper{    typedef typename mpl::if_< T(0) == N,                     mpl::identity< integer_sequence<T,I...> >,                   make_helper< T, N-1, N-1,I...>                 >::type;};测试make_integer_sequence我的主要功能是:int main(){     #define GEN(z,n,temp)   \     typedef make_integer_sequence< int, n >  BOOST_PP_CAT(int_seq,n) ;    BOOST_PP_REPEAT(256, GEN, ~);}我用GCC 4.8.0在一个四核i5系统上用8GB的RAM编写了程序。成功的编译花费了4秒。但是,当我将GEN宏更改为:int main() {#define GEN(z,n,temp) \typedef make_integer_sequence< int, n * 4 > BOOST_PP_CAT(int_seq, n) ;BOOST_PP_REPEAT(256, GEN, ~ );}编译失败,并输出了错误消息:虚拟内存耗尽。有人能解释一下这个错误吗?是什么原因造成的?编辑:我将测试简化为:int main(){    typedef make_integer_sequence< int, 4096 > int_seq4096;}然后,我成功地编译了GCC 4.8.0-fTemplate-Depth=65536。然而,第二个测试:int main(){     typedef make_integer_sequence< int, 16384 > int_seq16384;}没有用GCC 4.8.0f模板深度=65536编译,导致错误:虚拟内存耗尽。因此,我的问题是,如何减少模板深度实例化?你好,Khurshid。
查看完整描述

3 回答

?
森栏

TA贡献1810条经验 获得超5个赞

这是一个log N对于模板实例化甚至不需要增加最大深度的实现,并且编译速度相当快:


// using aliases for cleaner syntax

template<class T> using Invoke = typename T::type;


template<unsigned...> struct seq{ using type = seq; };


template<class S1, class S2> struct concat;


template<unsigned... I1, unsigned... I2>

struct concat<seq<I1...>, seq<I2...>>

  : seq<I1..., (sizeof...(I1)+I2)...>{};


template<class S1, class S2>

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


template<unsigned N> struct gen_seq;

template<unsigned N> using GenSeq = Invoke<gen_seq<N>>;


template<unsigned 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>{};



查看完整回答
反对 回复 2019-06-23
?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

我发现了非常快速和不必要的深入递归版本的实现make_index_sequence..在我的PC机上,它用N=1048576和2s进行编译。(PC:CentOS 6.4 x 86,i5,8 GB RAM,GCC-4.4.7-STD=c+0x-O2-Wall).


#include <cstddef> // for std::size_t


template< std::size_t ... i >

struct index_sequence

{

    typedef std::size_t value_type;


    typedef index_sequence<i...> type;


    // gcc-4.4.7 doesn't support `constexpr` and `noexcept`.

    static /*constexpr*/ std::size_t size() /*noexcept*/

    { 

        return sizeof ... (i); 

    }

};



// this structure doubles index_sequence elements.

// s- is number of template arguments in IS.

template< std::size_t s, typename IS >

struct doubled_index_sequence;


template< std::size_t s, std::size_t ... i >

struct doubled_index_sequence< s, index_sequence<i... > >

{

    typedef index_sequence<i..., (s + i)... > type;

};


// this structure incremented by one index_sequence, iff NEED-is true, 

// otherwise returns IS

template< bool NEED, typename IS >

struct inc_index_sequence;


template< typename IS >

struct inc_index_sequence<false,IS>{ typedef IS type; };


template< std::size_t ... i >

struct inc_index_sequence< true, index_sequence<i...> >

{

    typedef index_sequence<i..., sizeof...(i)> type;

};




// helper structure for make_index_sequence.

template< std::size_t N >

struct make_index_sequence_impl : 

           inc_index_sequence< (N % 2 != 0), 

                typename doubled_index_sequence< N / 2,

                           typename make_index_sequence_impl< N / 2> ::type

               >::type

       >

{};


 // helper structure needs specialization only with 0 element.

template<>struct make_index_sequence_impl<0>{ typedef index_sequence<> type; };




// OUR make_index_sequence,  gcc-4.4.7 doesn't support `using`, 

// so we use struct instead of it.

template< std::size_t N >

struct make_index_sequence : make_index_sequence_impl<N>::type {};


//index_sequence_for  any variadic templates

template< typename ... T >

struct index_sequence_for : make_index_sequence< sizeof...(T) >{};



// test

typedef make_index_sequence< 1024 * 1024 >::type a_big_index_sequence;

int main(){}


查看完整回答
反对 回复 2019-06-23
  • 3 回答
  • 0 关注
  • 548 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信