猿问

C+14 make_INTEGER序列的实现

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。


凤凰求蛊
浏览 549回答 3
3回答

森栏

这是一个log N对于模板实例化甚至不需要增加最大深度的实现,并且编译速度相当快:// using aliases for cleaner syntaxtemplate<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...>>&nbsp; : 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>{};

慕无忌1623718

我发现了非常快速和不必要的深入递归版本的实现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_ttemplate< std::size_t ... i >struct index_sequence{&nbsp; &nbsp; typedef std::size_t value_type;&nbsp; &nbsp; typedef index_sequence<i...> type;&nbsp; &nbsp; // gcc-4.4.7 doesn't support `constexpr` and `noexcept`.&nbsp; &nbsp; static /*constexpr*/ std::size_t size() /*noexcept*/&nbsp; &nbsp; {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return sizeof ... (i);&nbsp;&nbsp; &nbsp; }};// 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... > >{&nbsp; &nbsp; typedef index_sequence<i..., (s + i)... > type;};// this structure incremented by one index_sequence, iff NEED-is true,&nbsp;// otherwise returns IStemplate< 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...> >{&nbsp; &nbsp; typedef index_sequence<i..., sizeof...(i)> type;};// helper structure for make_index_sequence.template< std::size_t N >struct make_index_sequence_impl :&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inc_index_sequence< (N % 2 != 0),&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typename doubled_index_sequence< N / 2,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;typename make_index_sequence_impl< N / 2> ::type&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>::type&nbsp; &nbsp; &nbsp; &nbsp;>{};&nbsp;// helper structure needs specialization only with 0 element.template<>struct make_index_sequence_impl<0>{ typedef index_sequence<> type; };// OUR make_index_sequence,&nbsp; gcc-4.4.7 doesn't support `using`,&nbsp;// 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&nbsp; any variadic templatestemplate< typename ... T >struct index_sequence_for : make_index_sequence< sizeof...(T) >{};// testtypedef make_index_sequence< 1024 * 1024 >::type a_big_index_sequence;int main(){}
随时随地看视频慕课网APP
我要回答