I tried to implement the C++14 alias template make_integer_sequence
, which simplifies the creation of the class template 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.
To implement make_integer_sequence
we need a helper structure make_helper
.
template< class T , class N >
using make_integer_sequence = typename make_helper<T,N>::type;
Implementing make_helper
isn't too difficult.
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;
};
To test make_integer_sequence
I made this main function:
int main()
{
#define GEN(z,n,temp) \
typedef make_integer_sequence< int, n > BOOST_PP_CAT(int_seq,n) ;
BOOST_PP_REPEAT(256, GEN, ~);
}
I compiled the program with GCC 4.8.0, on a quad-core i5 system with 8GBs of RAM. Successful compilation took 4 seconds.
But, when I changed the GEN macro to:
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, ~ );
}
The compilation was unsuccessful and outputted the error message:
virtual memory exhausted.
Could somebody explain this error and what caused it?
EDIT:
I simplified the test to:
int main()
{
typedef make_integer_sequence< int, 4096 > int_seq4096;
}
I then successfully compiled with GCC 4.8.0 -ftemplate-depth=65536.
However this second test:
int main()
{
typedef make_integer_sequence< int, 16384 > int_seq16384;
}
Did not compile with GCC 4.8.0 -ftemplate-depth=65536, and resulted in the error:
virtual memory exhausted.
So, my question is, how do I decrease template deep instantiation?
Regards, Khurshid.
Here's a log N
implementation that doesn't even need an increased max-depth for template instantiations and compiles pretty fast:
// 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>{};